class_docstr: LIT WSGI application.
class_docstr_tok: ["LIT","WSGI","application","."]
code: def __init__(
      self,
      models: Mapping[str, lit_model.Model],
      datasets: Mapping[str, lit_dataset.Dataset],
      generators: Optional[
          Mapping[str, lit_components.Generator]
      ] = None,
      interpreters: Optional[
          Mapping[str, lit_components.Interpreter]
      ] = None,
      metrics: Optional[Mapping[str, lit_components.Metrics]] = None,
      annotators: Optional[list[lit_components.Annotator]] = None,
      layouts: Optional[layout.LitComponentLayouts] = None,
      dataset_loaders: Optional[DatasetLoadersMap] = None,
      model_loaders: Optional[ModelLoadersMap] = None,
      # General server config; see server_flags.py.
      data_dir: Optional[str] = None,
      warm_start: float = 0.0,
      warm_start_progress_indicator: Optional[
          ProgressIndicator
      ] = tqdm.tqdm,  # not in server_flags
      warm_projections: bool = False,
      client_root: Optional[str] = None,
      demo_mode: bool = False,
      default_layout: Optional[str] = None,
      canonical_url: Optional[str] = None,
      page_title: Optional[str] = None,
      development_demo: bool = False,
      inline_doc: Optional[str] = None,
      onboard_start_doc: Optional[str] = None,
      onboard_end_doc: Optional[str] = None,
      sync_state: bool = False,  # notebook-only; not in server_flags
      validate: Optional[flag_helpers.ValidationMode] = None,
      report_all: bool = False,
      enforce_dataset_fields_required: bool = False,
      strict_cache_id_validation: bool = False,
  ):
      if client_root is None:
          raise ValueError("client_root must be set on application")
      self._demo_mode = demo_mode
      self._development_demo = development_demo
      self._default_layout = default_layout
      self._canonical_url = canonical_url
      self._page_title = page_title
      self._inline_doc = inline_doc
      self._onboard_start_doc = onboard_start_doc
      self._onboard_end_doc = onboard_end_doc
      self._data_dir = data_dir
      if data_dir and not os.path.isdir(data_dir):
          os.mkdir(data_dir)
  
      self._caching_model_wrapper_kw = dict(
          cache_dir=self._data_dir,
          strict_id_validation=strict_cache_id_validation,
          id_hash_fn=caching.input_hash,
      )
  
      # TODO(lit-dev): override layouts instead of merging, to allow clients
      # to opt-out of the default bundled layouts. This will require updating
      # client code to manually merge when this is the desired behavior.
      self._layouts = dict(layout.DEFAULT_LAYOUTS, **(layouts or {}))
  
      self._model_loaders: ModelLoadersMap = model_loaders or {}
      self._models: dict[str, caching.CachingModelWrapper] = {}
      for name, model in models.items():
          if model_loaders is None:
              # Attempt to infer an init spec for the model before we lose access to
              # the original after wrapping it in a CachingModelWrapper.
              self._model_loaders[name] = (
                  type(model),
                  model.init_spec(),
              )
          # Wrap model in caching wrapper and add it to the app
          self._models[name] = caching.CachingModelWrapper(
              model, name, **self._caching_model_wrapper_kw
          )
  
      self._annotators: list[lit_components.Annotator] = (
          annotators or []
      )
      self._saved_datapoints = {}
      self._saved_datapoints_lock = threading.Lock()
  
      tmp_datasets: dict[str, lit_dataset.Dataset] = dict(datasets)
      # TODO(b/202210900): get rid of this, just dynamically create the empty
      # dataset on the frontend.
      tmp_datasets[_EMPTY_DATASET_KEY] = lit_dataset.NoneDataset(
          self._models
      )
  
      self._dataset_loaders: DatasetLoadersMap = dataset_loaders or {}
      self._datasets: dict[str, lit_dataset.IndexedDataset] = {}
      for name, ds in tmp_datasets.items():
          if dataset_loaders is None:
              # Attempt to infer an init spec for the dataset before we lose access to
              # the original during dataset annotation and indexing.
              self._dataset_loaders[name] = (type(ds), ds.init_spec())
          # Anotate the dataset
          annotated_ds = self._run_annotators(ds)
          # Index the annotated dataset and add it to the app
          self._datasets[name] = lit_dataset.IndexedDataset(
              base=annotated_ds, id_fn=caching.input_hash
          )
  
      # Generator initialization
      if generators is not None:
          self._generators = generators
      else:
          self._generators = core.default_generators()
  
      # Interpreter initialization
      if interpreters is not None:
          self._interpreters = (
              core.required_interpreters() | interpreters
          )
      else:
          self._interpreters = core.default_interpreters(self._models)
  
      if metrics is not None:
          self._metrics = metrics
      else:
          self._metrics = core.default_metrics()
  
      # Component to sync state from TS -> Python. Used in notebooks.
      if sync_state:
          self.ui_state_tracker = ui_state.UIStateTracker()
      else:
          self.ui_state_tracker = None
  
      # Information on models, datasets, and other components.
      self._info = self._build_metadata()
  
      # Validate datasets and models if specified.
      self._validate(
          validate,
          enforce_dataset_fields_required=enforce_dataset_fields_required,
          report_all=report_all,
      )
  
      # Optionally, run models to pre-populate cache.
      if warm_projections:
          logging.info(
              "Projection (dimensionality reduction) warm-start requested; "
              "will do full warm-start for all models since predictions are needed."
          )
          warm_start = 1.0
  
      if warm_start > 0:
          self._warm_start(
              rate=warm_start,
              progress_indicator=warm_start_progress_indicator,
          )
          self.save_cache()
          if warm_start >= 1:
              warm_projections = True
  
      # If you add a new embedding projector that should be warm-started,
      # also add it to the list here.
      # TODO(lit-dev): add some registry mechanism / automation if this grows to
      # more than 2-3 projection types.
      if warm_projections:
          self._warm_projections(["pca", "umap"])
  
      handlers = {
          # Metadata endpoints.
          "/get_info": self._get_info,
          # Dataset-related endpoints.
          "/get_dataset": self._get_dataset,
          "/create_dataset": self._create_dataset,
          "/create_model": self._create_model,
          "/get_generated": self._get_generated,
          "/save_datapoints": self._save_datapoints,
          "/load_datapoints": self._load_datapoints,
          "/annotate_new_data": self._annotate_new_data,
          "/post_new_data": self._post_new_data,
          "/fetch_new_data": self._fetch_new_data,
          "/remove_new_data": self._remove_new_data,
          "/push_ui_state": self._push_ui_state,
          # Model prediction endpoints.
          "/get_preds": self._get_preds,
          "/get_interpretations": self._get_interpretations,
          "/get_metrics": self._get_metrics,
      }
      wrapped_handlers = {
          k: self.make_handler(v) for k, v in handlers.items()
      }
  
      self._wsgi_app = wsgi_app.App(
          # Wrap endpoint fns to take (handler, request, environ)
          handlers=wrapped_handlers,
          project_root=client_root,
          index_file="static/index.html",
      )
  
imports: from collections.abc import Callable, Iterable, Mapping, Sequence
  import functools
  import glob
  import math
  import os
  import random
  import threading
  import time
  from typing import Any, Optional, TypedDict, Union
  from absl import logging
  from lit_nlp.api import components
  from lit_nlp.api import dataset
  from lit_nlp.api import layout
  from lit_nlp.api import model
  from lit_nlp.api import types
  from lit_nlp.components import core
  from lit_nlp.lib import caching
  from lit_nlp.lib import flag_helpers
  from lit_nlp.lib import serialize
  from lit_nlp.lib import ui_state
  from lit_nlp.lib import utils
  from lit_nlp.lib import validation
  from lit_nlp.lib import wsgi_app
  import tqdm
label_desc: Use image node_id 24 to create a new LitApp object from inherited base classes: object with example: obj = LitApp(models, datasets, generators, interpreters, metrics, annotators, layouts, dataset_loaders, model_loaders, data_dir, warm_start, warm_start_progress_indicator, warm_projections, client_root, demo_mode, default_layout, canonical_url, page_title, development_demo, inline_doc, onboard_start_doc, onboard_end_doc, sync_state, validate, report_all, enforce_dataset_fields_required, strict_cache_id_validation)