class_docstr: caliban container spec
  
  This class contains the information specifying how to generate a docker
  container for use in caliban.
  
  Please do not instantiate this class directly via its constructor.
  Instead, use the ContainerSpec.get_or_create() method, or query the database
  using a session.query() call. The get_or_create() method returns an existing
  container spec if a matching instance already exists in the database, or
  creates a new instance otherwise.
  
  Properties:
  id (int): unique identifier, populated by backend database
  user (str): user who created this instance
  spec (JSON): json dictionary containing the docker creation parameters
  created (datetime): timestamp of creation time of this instance
  experiments (iterable of Experiment instances): Experiment instances based on
              this ContainerSpec
class_docstr_tok: ["caliban","container","spec","This","class","contains","the","information","specifying","how","to","generate","a","docker","container","for","use","in","caliban",".","Please","do","not","instantiate","this","class","directly","via","its","constructor",".","Instead",",","use","the","ContainerSpec.get_or_create","(",")","method",",","or","query","the","database","using","a","session.query","(",")","call",".","The","get_or_create","(",")","method","returns","an","existing","container","spec","if","a","matching","instance","already","exists","in","the","database",",","or","creates","a","new","instance","otherwise",".","Properties",":","id","(","int",")",":","unique","identifier",",","populated","by","backend","database","user","(","str",")",":","user","who","created","this","instance","spec","(","JSON",")",":","json","dictionary","containing","the","docker","creation","parameters","created","(","datetime",")",":","timestamp","of","creation","time","of","this","instance","experiments","(","iterable","of","Experiment","instances",")",":","Experiment","instances","based","on","this","ContainerSpec"]
docstr: gets an existing instance, or creates a new one as necessary
  
  Args:
  session: a sqlalchemy session
  spec: a dictionary containing the docker creation parameters
  user: the user creating this instance, if None then user is detected
  
  Returns:
  a ContainerSpec instance
docstr_tok: ["gets","an","existing","instance",",","or","creates","a","new","one","as","necessary","Args",":","session",":","a","sqlalchemy","session","spec",":","a","dictionary","containing","the","docker","creation","parameters","user",":","the","user","creating","this","instance",",","if","None","then","user","is","detected","Returns",":","a","ContainerSpec","instance"]
code: def get_or_create(
      cls,
      session: Session,
      spec: Dict[str, Any],
      user: Optional[str] = None,
  ) -> "ContainerSpec":
      """gets an existing instance, or creates a new one as necessary
  
      Args:
      session: a sqlalchemy session
      spec: a dictionary containing the docker creation parameters
      user: the user creating this instance, if None then user is detected
  
      Returns:
      a ContainerSpec instance
      """
      new_spec = ContainerSpec(spec, user)
  
      existing = session.query(ContainerSpec)
      existing = existing.filter(
          ContainerSpec.user == new_spec.user,
          ContainerSpec.spec.cast(String) == json.dumps(new_spec.spec),
      )
  
      return existing.first() or new_spec
  
imports: import json
  from collections import OrderedDict
  from datetime import datetime
  from enum import Enum
  from typing import Any, Dict, List, Optional
  import sqlalchemy
  from sqlalchemy import JSON, Column, DateTime, ForeignKey, Integer, String
  from sqlalchemy.engine.base import Engine
  from sqlalchemy.ext.declarative import declarative_base
  from sqlalchemy.orm import Session, backref, relationship, sessionmaker
  from sqlalchemy.orm.session import object_session
  from caliban.util import current_user
label_desc: Use image node_id 2 for calling the ContainerSpec obj's underlying member method code with example usage: obj.get_or_create(cls, session, spec, user) and returns: unknown