class_docstr: Maps names of columns to sequences or arrays.
  
  The ``ColumnDataSource`` is a fundamental data structure of Bokeh. Most
  plots, data tables, etc. will be driven by a ``ColumnDataSource``.
  
  If the ``ColumnDataSource`` initializer is called with a single argument that
  can be any of the following:
  
  * A Python ``dict`` that maps string names to sequences of values, e.g.
    lists, arrays, etc.
  
    .. code-block:: python
  
        data = {'x': [1,2,3,4], 'y': np.array([10.0, 20.0, 30.0, 40.0])}
  
        source = ColumnDataSource(data)
  
  .. note::
      ``ColumnDataSource`` only creates a shallow copy of ``data``. Use e.g.
      ``ColumnDataSource(copy.deepcopy(data))`` if initializing from another
      ``ColumnDataSource.data`` object that you want to keep independent.
  
  * A Pandas ``DataFrame`` object
  
    .. code-block:: python
  
        source = ColumnDataSource(df)
  
    In this case the CDS will have columns corresponding to the columns of
    the ``DataFrame``. If the ``DataFrame`` columns have multiple levels,
    they will be flattened using an underscore (e.g. level_0_col_level_1_col).
    The index of the ``DataFrame`` will be flattened to an ``Index`` of tuples
    if it's a ``MultiIndex``, and then reset using ``reset_index``. The result
    will be a column with the same name if the index was named, or
    level_0_name_level_1_name if it was a named ``MultiIndex``. If the
    ``Index`` did not have a name or the ``MultiIndex`` name could not be
    flattened/determined, the ``reset_index`` function will name the index column
    ``index``, or ``level_0`` if the name ``index`` is not available.
  
  * A Pandas ``GroupBy`` object
  
    .. code-block:: python
  
        group = df.groupby(('colA', 'ColB'))
  
    In this case the CDS will have columns corresponding to the result of
    calling ``group.describe()``. The ``describe`` method generates columns
    for statistical measures such as ``mean`` and ``count`` for all the
    non-grouped original columns. The CDS columns are formed by joining
    original column names with the computed measure. For example, if a
    ``DataFrame`` has columns ``'year'`` and ``'mpg'``. Then passing
    ``df.groupby('year')`` to a CDS will result in columns such as
    ``'mpg_mean'``
  
    If the ``GroupBy.describe`` result has a named index column, then
    CDS will also have a column with this name. However, if the index name
    (or any subname of a ``MultiIndex``) is ``None``, then the CDS will have
    a column generically named ``index`` for the index.
  
    Note this capability to adapt ``GroupBy`` objects may only work with
    Pandas ``>=0.20.0``.
  
  .. note::
      There is an implicit assumption that all the columns in a given
      ``ColumnDataSource`` all have the same length at all times. For this
      reason, it is usually preferable to update the ``.data`` property
      of a data source "all at once".
docstr: Efficiently update data source columns at specific locations
  
  If it is only necessary to update a small subset of data in a
  ``ColumnDataSource``, this method can be used to efficiently update only
  the subset, instead of requiring the entire data set to be sent.
  
  This method should be passed a dictionary that maps column names to
  lists of tuples that describe a patch change to apply. To replace
  individual items in columns entirely, the tuples should be of the
  form:
  
  .. code-block:: python
  
      (index, new_value)  # replace a single column value
  
      # or
  
      (slice, new_values) # replace several column values
  
  Values at an index or slice will be replaced with the corresponding
  new values.
  
  In the case of columns whose values are other arrays or lists, (e.g.
  image or patches glyphs), it is also possible to patch "subregions".
  In this case the first item of the tuple should be a whose first
  element is the index of the array item in the CDS patch, and whose
  subsequent elements are integer indices or slices into the array item:
  
  .. code-block:: python
  
      # replace the entire 10th column of the 2nd array:
  
        +----------------- index of item in column data source
        |
        |       +--------- row subindex into array item
        |       |
        |       |       +- column subindex into array item
        V       V       V
      ([2, slice(None), 10], new_values)
  
  Imagining a list of 2d NumPy arrays, the patch above is roughly
  equivalent to:
  
  .. code-block:: python
  
      data = [arr1, arr2, ...]  # list of 2d arrays
  
      data[2][:, 10] = new_data
  
  There are some limitations to the kinds of slices and data that can
  be accepted.
  
  * Negative ``start``, ``stop``, or ``step`` values for slices will
    result in a ``ValueError``.
  
  * In a slice, ``start > stop`` will result in a ``ValueError``
  
  * When patching 1d or 2d subitems, the subitems must be NumPy arrays.
  
  * New values must be supplied as a **flattened one-dimensional array**
    of the appropriate size.
  
  Args:
      patches (dict[str, list[tuple]]) : lists of patches for each column
  
  Returns:
      None
  
  Raises:
      ValueError
  
  Example:
  
  The following example shows how to patch entire column elements. In this case,
  
  .. code-block:: python
  
      source = ColumnDataSource(data=dict(foo=[10, 20, 30], bar=[100, 200, 300]))
  
      patches = {
          'foo' : [ (slice(2), [11, 12]) ],
          'bar' : [ (0, 101), (2, 301) ],
      }
  
      source.patch(patches)
  
  After this operation, the value of the ``source.data`` will be:
  
  .. code-block:: python
  
      dict(foo=[11, 12, 30], bar=[101, 200, 301])
  
  For a more comprehensive example, see :bokeh-tree:`examples/server/app/patch_app.py`.
docstr_tok: ["Efficiently","update","data","source","columns","at","specific","locations","If","it","is","only","necessary","to","update","a","small","subset","of","data","in","a","``","ColumnDataSource","``",",","this","method","can","be","used","to","efficiently","update","only","the","subset",",","instead","of","requiring","the","entire","data","set","to","be","sent",".","This","method","should","be","passed","a","dictionary","that","maps","column","names","to","lists","of","tuples","that","describe","a","patch","change","to","apply",".","To","replace","individual","items","in","columns","entirely",",","the","tuples","should","be","of","the","form",":","..","code-block",":",":","python","(","index",",","new_value",")","#","replace","a","single","column","value","#","or","(","slice",",","new_values",")","#","replace","several","column","values","Values","at","an","index","or","slice","will","be","replaced","with","the","corresponding","new","values",".","In","the","case","of","columns","whose","values","are","other","arrays","or","lists",",","(","e.g",".","image","or","patches","glyphs",")",",","it","is","also","possible","to","patch","``","subregions","''",".","In","this","case","the","first","item","of","the","tuple","should","be","a","whose","first","element","is","the","index","of","the","array","item","in","the","CDS","patch",",","and","whose","subsequent","elements","are","integer","indices","or","slices","into","the","array","item",":","..","code-block",":",":","python","#","replace","the","entire","10th","column","of","the","2nd","array",":","+","--","--","--","--","--","--","--","--","-","index","of","item","in","column","data","source","|","|","+","--","--","--","--","-","row","subindex","into","array","item","|","|","|","|","+-","column","subindex","into","array","item","V","V","V","(","[","2",",","slice","(","None",")",",","10","]",",","new_values",")","Imagining","a","list","of","2d","NumPy","arrays",",","the","patch","above","is","roughly","equivalent","to",":","..","code-block",":",":","python","data","=","[","arr1",",","arr2",",","...","]","#","list","of","2d","arrays","data","[","2","]","[",":",",","10","]","=","new_data","There","are","some","limitations","to","the","kinds","of","slices","and","data","that","can","be","accepted",".","*","Negative","``","start","``",",","``","stop","``",",","or","``","step","``","values","for","slices","will","result","in","a","``","ValueError","``",".","*","In","a","slice",",","``","start",">","stop","``","will","result","in","a","``","ValueError","``","*","When","patching","1d","or","2d","subitems",",","the","subitems","must","be","NumPy","arrays",".","*","New","values","must","be","supplied","as","a","*","*","flattened","one-dimensional","array","*","*","of","the","appropriate","size",".","Args",":","patches","(","dict","[","str",",","list","[","tuple","]","]",")",":","lists","of","patches","for","each","column","Returns",":","None","Raises",":","ValueError","Example",":","The","following","example","shows","how","to","patch","entire","column","elements",".","In","this","case",",","..","code-block",":",":","python","source","=","ColumnDataSource","(","data=dict","(","foo=","[","10",",","20",",","30","]",",","bar=","[","100",",","200",",","300","]",")",")","patches","=","{","'foo","'",":","[","(","slice","(","2",")",",","[","11",",","12","]",")","]",",","'bar","'",":","[","(","0",",","101",")",",","(","2",",","301",")","]",",","}","source.patch","(","patches",")","After","this","operation",",","the","value","of","the","``","source.data","``","will","be",":","..","code-block",":",":","python","dict","(","foo=","[","11",",","12",",","30","]",",","bar=","[","101",",","200",",","301","]",")","For","a","more","comprehensive","example",",","see",":","bokeh-tree",":","`","examples\/server\/app\/patch_app.py","`","."]
code: def patch(
      self, patches: Patches, setter: Setter | None = None
  ) -> None:
      """Efficiently update data source columns at specific locations
  
      If it is only necessary to update a small subset of data in a
      ``ColumnDataSource``, this method can be used to efficiently update only
      the subset, instead of requiring the entire data set to be sent.
  
      This method should be passed a dictionary that maps column names to
      lists of tuples that describe a patch change to apply. To replace
      individual items in columns entirely, the tuples should be of the
      form:
  
      .. code-block:: python
  
          (index, new_value)  # replace a single column value
  
          # or
  
          (slice, new_values) # replace several column values
  
      Values at an index or slice will be replaced with the corresponding
      new values.
  
      In the case of columns whose values are other arrays or lists, (e.g.
      image or patches glyphs), it is also possible to patch "subregions".
      In this case the first item of the tuple should be a whose first
      element is the index of the array item in the CDS patch, and whose
      subsequent elements are integer indices or slices into the array item:
  
      .. code-block:: python
  
          # replace the entire 10th column of the 2nd array:
  
            +----------------- index of item in column data source
            |
            |       +--------- row subindex into array item
            |       |
            |       |       +- column subindex into array item
            V       V       V
          ([2, slice(None), 10], new_values)
  
      Imagining a list of 2d NumPy arrays, the patch above is roughly
      equivalent to:
  
      .. code-block:: python
  
          data = [arr1, arr2, ...]  # list of 2d arrays
  
          data[2][:, 10] = new_data
  
      There are some limitations to the kinds of slices and data that can
      be accepted.
  
      * Negative ``start``, ``stop``, or ``step`` values for slices will
        result in a ``ValueError``.
  
      * In a slice, ``start > stop`` will result in a ``ValueError``
  
      * When patching 1d or 2d subitems, the subitems must be NumPy arrays.
  
      * New values must be supplied as a **flattened one-dimensional array**
        of the appropriate size.
  
      Args:
          patches (dict[str, list[tuple]]) : lists of patches for each column
  
      Returns:
          None
  
      Raises:
          ValueError
  
      Example:
  
      The following example shows how to patch entire column elements. In this case,
  
      .. code-block:: python
  
          source = ColumnDataSource(data=dict(foo=[10, 20, 30], bar=[100, 200, 300]))
  
          patches = {
              'foo' : [ (slice(2), [11, 12]) ],
              'bar' : [ (0, 101), (2, 301) ],
          }
  
          source.patch(patches)
  
      After this operation, the value of the ``source.data`` will be:
  
      .. code-block:: python
  
          dict(foo=[11, 12, 30], bar=[101, 200, 301])
  
      For a more comprehensive example, see :bokeh-tree:`examples/server/app/patch_app.py`.
  
      """
      extra = set(patches.keys()) - set(self.data.keys())
  
      if extra:
          raise ValueError(
              "Can only patch existing columns (extra: %s)"
              % ", ".join(sorted(extra))
          )
  
      for name, patch in patches.items():
          col_len = len(self.data[name])
  
          for ind, _ in patch:
              # integer index, patch single value of 1d column
              if isinstance(ind, int):
                  if ind > col_len or ind < 0:
                      raise ValueError(
                          "Out-of bounds index (%d) in patch for column: %s"
                          % (ind, name)
                      )
  
              # slice index, patch multiple values of 1d column
              elif isinstance(ind, slice):
                  _check_slice(ind)
                  if ind.stop is not None and ind.stop > col_len:
                      raise ValueError(
                          "Out-of bounds slice index stop (%d) in patch for column: %s"
                          % (ind.stop, name)
                      )
  
              # multi-index, patch sub-regions of "n-d" column
              elif isinstance(ind, (list, tuple)):
                  if len(ind) == 0:
                      raise ValueError(
                          "Empty (length zero) patch multi-index"
                      )
  
                  if len(ind) == 1:
                      raise ValueError(
                          "Patch multi-index must contain more than one subindex"
                      )
  
                  ind_0 = ind[0]
                  if not isinstance(ind_0, int):
                      raise ValueError(
                          "Initial patch sub-index may only be integer, got: %s"
                          % ind_0
                      )
  
                  if ind_0 > col_len or ind_0 < 0:
                      raise ValueError(
                          "Out-of bounds initial sub-index (%d) in patch for column: %s"
                          % (ind, name)
                      )
  
                  if not isinstance(self.data[name][ind_0], np.ndarray):
                      raise ValueError(
                          "Can only sub-patch into columns with NumPy array items"
                      )
  
                  if len(self.data[name][ind_0].shape) != (
                      len(ind) - 1
                  ):
                      raise ValueError(
                          "Shape mismatch between patch slice and sliced data"
                      )
  
                  elif isinstance(ind_0, slice):
                      _check_slice(ind_0)
                      if (
                          ind_0.stop is not None
                          and ind_0.stop > col_len
                      ):
                          raise ValueError(
                              "Out-of bounds initial slice sub-index stop (%d) in patch for column: %s"
                              % (ind.stop, name)
                          )
  
                  # Note: bounds of sub-indices after the first are not checked!
                  for subind in ind[1:]:
                      if not isinstance(subind, (int, slice)):
                          raise ValueError(
                              "Invalid patch sub-index: %s" % subind
                          )
                      if isinstance(subind, slice):
                          _check_slice(subind)
  
              else:
                  raise ValueError("Invalid patch index: %s" % ind)
  
      self.data._patch(self.document, self, patches, setter)
  
imports: from __future__ import annotations
  import logging
  from typing import TYPE_CHECKING, Any, Sequence, Union, overload
  import numpy
  from ..core.has_props import abstract
  from ..core.properties import JSON, Any, Bool, ColumnData, Dict, Enum, Instance, InstanceDefault, Int, Nullable, Object, Readonly, Required, Seq, String
  from ..model import Model
  from ..util.deprecation import deprecated
  from ..util.serialization import convert_datetime_array
  from ..util.warnings import BokehUserWarning, warn
  from .callbacks import CustomJS
  from .filters import AllIndices, Filter, IntersectionFilter
  from .selections import Selection, SelectionPolicy, UnionRenderers
label_desc: Use image node_id 15 for calling the ColumnDataSource obj's underlying member method code with example usage: obj.patch(patches, setter) without return types