class_docstr: caliban job spec
  
  This class constitutes a compute-platform-specific specification for
  executing a job. This class maps an Experiment to a specific instance
  for execution, and is thus associated with an Experiment and a specific
  Platform. A job spec can have multiple job instances associated with it,
  corresponding to executions of the spec.
  
  Please do not instantiate this class directly via its constructor.
  Instead, use the JobSpec.get_or_create() method, or query the database
  using a session.query() call. The get_or_create() method returns an existing
  job spec if a matching instance already exists in the database, or
  creates a new instance otherwise.
  
  properties:
  
  id (int): unique id generated by database backend
  created (datetime): creation timestamp
  spec (JSON): dictionary describing job spec for given compute platform
  platform (Platform): compute platform
  experiment (Experiment): experiment for this job spec
  jobs (Iterable[Job]): job instances of this spec
class_docstr_tok: ["caliban","job","spec","This","class","constitutes","a","compute-platform-specific","specification","for","executing","a","job",".","This","class","maps","an","Experiment","to","a","specific","instance","for","execution",",","and","is","thus","associated","with","an","Experiment","and","a","specific","Platform",".","A","job","spec","can","have","multiple","job","instances","associated","with","it",",","corresponding","to","executions","of","the","spec",".","Please","do","not","instantiate","this","class","directly","via","its","constructor",".","Instead",",","use","the","JobSpec.get_or_create","(",")","method",",","or","query","the","database","using","a","session.query","(",")","call",".","The","get_or_create","(",")","method","returns","an","existing","job","spec","if","a","matching","instance","already","exists","in","the","database",",","or","creates","a","new","instance","otherwise",".","properties",":","id","(","int",")",":","unique","id","generated","by","database","backend","created","(","datetime",")",":","creation","timestamp","spec","(","JSON",")",":","dictionary","describing","job","spec","for","given","compute","platform","platform","(","Platform",")",":","compute","platform","experiment","(","Experiment",")",":","experiment","for","this","job","spec","jobs","(","Iterable","[","Job","]",")",":","job","instances","of","this","spec"]
code: def __repr__(self):
      return f"<JobSpec(id: {self.id} created: {self.created})>"
  
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 4 for calling the JobSpec obj's underlying member method code with example usage: obj.__repr__() and returns: str, self, str, self, str