code: def grid(
      children: Any = [],
      sizing_mode: SizingModeType | None = None,
      nrows: int | None = None,
      ncols: int | None = None,
  ) -> GridBox:
      """
      Conveniently create a grid of layoutable objects.
  
      Grids are created by using ``GridBox`` model. This gives the most control over
      the layout of a grid, but is also tedious and may result in unreadable code in
      practical applications. ``grid()`` function remedies this by reducing the level
      of control, but in turn providing a more convenient API.
  
      Supported patterns:
  
      1. Nested lists of layoutable objects. Assumes the top-level list represents
         a column and alternates between rows and columns in subsequent nesting
         levels. One can use ``None`` for padding purpose.
  
         >>> grid([p1, [[p2, p3], p4]])
         GridBox(children=[
             (p1, 0, 0, 1, 2),
             (p2, 1, 0, 1, 1),
             (p3, 2, 0, 1, 1),
             (p4, 1, 1, 2, 1),
         ])
  
      2. Nested ``Row`` and ``Column`` instances. Similar to the first pattern, just
         instead of using nested lists, it uses nested ``Row`` and ``Column`` models.
         This can be much more readable that the former. Note, however, that only
         models that don't have ``sizing_mode`` set are used.
  
         >>> grid(column(p1, row(column(p2, p3), p4)))
         GridBox(children=[
             (p1, 0, 0, 1, 2),
             (p2, 1, 0, 1, 1),
             (p3, 2, 0, 1, 1),
             (p4, 1, 1, 2, 1),
         ])
  
      3. Flat list of layoutable objects. This requires ``nrows`` and/or ``ncols`` to
         be set. The input list will be rearranged into a 2D array accordingly. One
         can use ``None`` for padding purpose.
  
         >>> grid([p1, p2, p3, p4], ncols=2)
         GridBox(children=[
             (p1, 0, 0, 1, 1),
             (p2, 0, 1, 1, 1),
             (p3, 1, 0, 1, 1),
             (p4, 1, 1, 1, 1),
         ])
  
      """
  
      @dataclass
      class row:
          children: list[row | col]
  
      @dataclass
      class col:
          children: list[row | col]
  
      @dataclass
      class Item:
          layout: LayoutDOM
          r0: int
          c0: int
          r1: int
          c1: int
  
      @dataclass
      class Grid:
          nrows: int
          ncols: int
          items: list[Item]
  
      def flatten(layout) -> GridBox:
          def gcd(a: int, b: int) -> int:
              a, b = abs(a), abs(b)
              while b != 0:
                  a, b = b, a % b
              return a
  
          def lcm(a: int, *rest: int) -> int:
              for b in rest:
                  a = (a * b) // gcd(a, b)
              return a
  
          def nonempty(child: Grid) -> bool:
              return child.nrows != 0 and child.ncols != 0
  
          def _flatten(layout: row | col | LayoutDOM) -> Grid:
              if isinstance(layout, row):
                  children = list(
                      filter(nonempty, map(_flatten, layout.children))
                  )
                  if not children:
                      return Grid(0, 0, [])
  
                  nrows = lcm(*[child.nrows for child in children])
                  ncols = sum(child.ncols for child in children)
  
                  items: list[Item] = []
                  offset = 0
                  for child in children:
                      factor = nrows // child.nrows
  
                      for i in child.items:
                          items.append(
                              Item(
                                  i.layout,
                                  factor * i.r0,
                                  i.c0 + offset,
                                  factor * i.r1,
                                  i.c1 + offset,
                              )
                          )
  
                      offset += child.ncols
  
                  return Grid(nrows, ncols, items)
              elif isinstance(layout, col):
                  children = list(
                      filter(nonempty, map(_flatten, layout.children))
                  )
                  if not children:
                      return Grid(0, 0, [])
  
                  nrows = sum(child.nrows for child in children)
                  ncols = lcm(*[child.ncols for child in children])
  
                  items = []
                  offset = 0
                  for child in children:
                      factor = ncols // child.ncols
  
                      for i in child.items:
                          items.append(
                              Item(
                                  i.layout,
                                  i.r0 + offset,
                                  factor * i.c0,
                                  i.r1 + offset,
                                  factor * i.c1,
                              )
                          )
  
                      offset += child.nrows
  
                  return Grid(nrows, ncols, items)
              else:
                  return Grid(1, 1, [Item(layout, 0, 0, 1, 1)])
  
          grid = _flatten(layout)
  
          children = []
          for i in grid.items:
              if i.layout is not None:
                  children.append(
                      (i.layout, i.r0, i.c0, i.r1 - i.r0, i.c1 - i.c0)
                  )
  
          return GridBox(children=children)
  
      layout: row | col
      if isinstance(children, list):
          if nrows is not None or ncols is not None:
              N = len(children)
              if ncols is None:
                  ncols = math.ceil(N / nrows)
              layout = col(
                  [
                      row(children[i : i + ncols])
                      for i in range(0, N, ncols)
                  ]
              )
          else:
  
              def traverse(children: list[LayoutDOM], level: int = 0):
                  if isinstance(children, list):
                      container = col if level % 2 == 0 else row
                      return container(
                          [
                              traverse(child, level + 1)
                              for child in children
                          ]
                      )
                  else:
                      return children
  
              layout = traverse(children)
      elif isinstance(children, LayoutDOM):
  
          def is_usable(child: LayoutDOM) -> bool:
              return _has_auto_sizing(child) and child.spacing == 0
  
          def traverse(item: LayoutDOM, top_level: bool = False):
              if isinstance(item, FlexBox) and (
                  top_level or is_usable(item)
              ):
                  container = col if isinstance(item, Column) else row
                  return container(list(map(traverse, item.children)))
              else:
                  return item
  
          layout = traverse(children, top_level=True)
      elif isinstance(children, str):
          raise NotImplementedError
      else:
          raise ValueError("expected a list, string or model")
  
      grid = flatten(layout)
  
      if sizing_mode is not None:
          grid.sizing_mode = sizing_mode
  
          for child in grid.children:
              layout = child[0]
              if _has_auto_sizing(layout):
                  layout.sizing_mode = sizing_mode
  
      return grid
  
imports: from __future__ import annotations
  import logging
  import math
  from collections import defaultdict
  from typing import TYPE_CHECKING, Any, Callable, Iterable, Iterator, Literal, Sequence, TypeVar, Union, overload
  from .core.enums import Location, LocationType, SizingModeType
  from .core.property.singletons import Undefined, UndefinedType
  from .models import Column, CopyTool, ExamineTool, FlexBox, FullscreenTool, GridBox, GridPlot, LayoutDOM, Plot, Row, SaveTool, Spacer, Tool, Toolbar, ToolProxy, UIElement
  from .util.dataclasses import dataclass
  from .util.warnings import warn
label_desc: Use image node_id 15 for calling a global function with example usage: grid(children, sizing_mode, nrows, ncols) and returns: grid, GridBox, a, a, unknown, Grid, unknown, Grid, Grid, Grid, container, children, container, item, Grid