class_docstr: EnvironmentController inherits from BaseController and manages business logic related to the
  environment.
  
  Methods
  -------
  create(dictionary)
      Create an environment within the project
  build(id)
      Build the environment for use within the project
  list()
      List all environments within the project
  delete(id)
      Delete the specified environment from the project
class_docstr_tok: ["EnvironmentController","inherits","from","BaseController","and","manages","business","logic","related","to","the","environment",".","Methods","--","--","--","-","create","(","dictionary",")","Create","an","environment","within","the","project","build","(","id",")","Build","the","environment","for","use","within","the","project","list","(",")","List","all","environments","within","the","project","delete","(","id",")","Delete","the","specified","environment","from","the","project"]
docstr: Create an environment
  
  Parameters
  ----------
  dictionary : dict
      optional values to populate required environment entity args
          paths : list, optional
              list of absolute or relative filepaths and/or dirpaths to collect with destination names
              (e.g. "/path/to/file>hello", "/path/to/file2", "/path/to/dir>newdir")
              (default if none provided is to pull from project environment folder and project root. If none found create default definition)
          name : str, optional
              name of the environment
              (default is None)
          description : str, optional
              description of the environment
              (default is None)
  save_hardware_file : bool
      boolean to save hardware file along with other files
      (default is True to save the file and create distinct hashes based on software and hardware)
  
  Returns
  -------
  Environment
      returns an object representing the environment created
  
  Raises
  ------
  EnvironmentDoesNotExist
      if there is no environment found after given parameters and defaults are checked
  PathDoesNotExist
      if any source paths provided do not exist
docstr_tok: ["Create","an","environment","Parameters","--","--","--","--","--","dictionary",":","dict","optional","values","to","populate","required","environment","entity","args","paths",":","list",",","optional","list","of","absolute","or","relative","filepaths","and\/or","dirpaths","to","collect","with","destination","names","(","e.g",".","``","\/path\/to\/file",">","hello","''",",","``","\/path\/to\/file2","''",",","``","\/path\/to\/dir",">","newdir","''",")","(","default","if","none","provided","is","to","pull","from","project","environment","folder","and","project","root",".","If","none","found","create","default","definition",")","name",":","str",",","optional","name","of","the","environment","(","default","is","None",")","description",":","str",",","optional","description","of","the","environment","(","default","is","None",")","save_hardware_file",":","bool","boolean","to","save","hardware","file","along","with","other","files","(","default","is","True","to","save","the","file","and","create","distinct","hashes","based","on","software","and","hardware",")","Returns","--","--","--","-","Environment","returns","an","object","representing","the","environment","created","Raises","--","--","--","EnvironmentDoesNotExist","if","there","is","no","environment","found","after","given","parameters","and","defaults","are","checked","PathDoesNotExist","if","any","source","paths","provided","do","not","exist"]
code: def create(self, dictionary, save_hardware_file=True):
      """Create an environment
  
      Parameters
      ----------
      dictionary : dict
          optional values to populate required environment entity args
              paths : list, optional
                  list of absolute or relative filepaths and/or dirpaths to collect with destination names
                  (e.g. "/path/to/file>hello", "/path/to/file2", "/path/to/dir>newdir")
                  (default if none provided is to pull from project environment folder and project root. If none found create default definition)
              name : str, optional
                  name of the environment
                  (default is None)
              description : str, optional
                  description of the environment
                  (default is None)
      save_hardware_file : bool
          boolean to save hardware file along with other files
          (default is True to save the file and create distinct hashes based on software and hardware)
  
      Returns
      -------
      Environment
          returns an object representing the environment created
  
      Raises
      ------
      EnvironmentDoesNotExist
          if there is no environment found after given parameters and defaults are checked
      PathDoesNotExist
          if any source paths provided do not exist
      """
      # Validate Inputs
      create_dict = {"model_id": self.model.id}
      create_dict["driver_type"] = self.environment_driver.type
  
      validate("create_environment", dictionary)
  
      # Create temp environment folder
      _temp_env_dir = get_datmo_temp_path(self.home)
      # Step 1: Populate a path list from the user inputs in a format compatible
      # with the input of the File Collection create function
      paths = []
  
      # a. add in user given paths as is if they exist
      if "paths" in dictionary and dictionary["paths"]:
          paths.extend(dictionary["paths"])
  
      # b. if there exists project environment directory AND no paths exist, add in absolute paths
      if not paths and os.path.isdir(
          self.environment_driver.environment_directory_path
      ):
          paths.extend(
              [
                  os.path.join(
                      self.environment_driver.environment_directory_path,
                      filepath,
                  )
                  for filepath in list_all_filepaths(
                      self.environment_driver.environment_directory_path
                  )
              ]
          )
  
      # c. add in default environment definition filepath as specified by the environment driver
      # if path exists and NO OTHER PATHS exist
      src_environment_filename = (
          self.environment_driver.get_default_definition_filename()
      )
      src_environment_filepath = os.path.join(
          self.home, src_environment_filename
      )
      _, environment_filename = os.path.split(src_environment_filepath)
      create_dict["definition_filename"] = environment_filename
      if not paths and os.path.exists(src_environment_filepath):
          paths.append(src_environment_filepath)
  
      # Step 2: Check existing paths and create files as needed to populate the
      # full environment within the temporary directory
  
      paths = self._setup_compatible_environment(
          create_dict,
          paths,
          _temp_env_dir,
          save_hardware_file=save_hardware_file,
      )
  
      # Step 3: Pass in all paths for the environment to the file collection create
      # If PathDoesNotExist is found for any source paths, then error
      if not paths:
          raise EnvironmentDoesNotExist()
      try:
          file_collection_obj = self.file_collection.create(paths)
      except PathDoesNotExist as e:
          raise PathDoesNotExist(
              __(
                  "error",
                  "controller.environment.create.filepath.dne",
                  str(e),
              )
          )
  
      # Step 4: Add file collection information to create dict and check unique hash
      create_dict["file_collection_id"] = file_collection_obj.id
      create_dict["unique_hash"] = file_collection_obj.filehash
      # Check if unique hash is unique or not.
      # If not, DO NOT CREATE Environment and return existing Environment object
      results = self.dal.environment.query(
          {"unique_hash": file_collection_obj.filehash}
      )
      if results:
          return results[0]
  
      # Step 5: Delete the temporary directory
      shutil.rmtree(_temp_env_dir)
  
      # Step 6: Add optional arguments to the Environment entity
      for optional_arg in ["name", "description"]:
          if optional_arg in dictionary:
              create_dict[optional_arg] = dictionary[optional_arg]
  
      # Step 7: Create environment and return
      return self.dal.environment.create(Environment(create_dict))
  
imports: import os
  import shutil
  from datmo.core.controller.base import BaseController
  from datmo.core.controller.file.file_collection import FileCollectionController
  from datmo.core.entity.environment import Environment
  from datmo.core.util.i18n import get
  from datmo.core.util.validation import validate
  from datmo.core.util.spinner import Spinner
  from datmo.core.util.json_store import JSONStore
  from datmo.core.util.misc_functions import get_datmo_temp_path, list_all_filepaths
  from datmo.core.util.exceptions import PathDoesNotExist, RequiredArgumentMissing, TooManyArgumentsFound, EnvironmentNotInitialized, UnstagedChanges, ArgumentError, EnvironmentDoesNotExist, ProjectNotInitialized
label_desc: Use image node_id 7 for calling the EnvironmentController obj's underlying member method code with example usage: obj.create(dictionary, save_hardware_file) and returns: self, results