docstr: Insert containers laid out as side-by-side columns.
  
  Inserts a number of multi-element containers laid out side-by-side and
  returns a list of container objects.
  
  To add elements to the returned containers, you can use "with" notation
  (preferred) or just call methods directly on the returned object. See
  examples below.
  
  Columns can only be placed inside other columns up to one level of nesting.
  
  .. warning::
      Columns cannot be placed inside other columns in the sidebar. This is only possible in the main area of the app.
  
  Parameters
  ----------
  spec : int or Iterable of numbers
      Controls the number and width of columns to insert. Can be one of:
  
      * An integer that specifies the number of columns. All columns have equal
        width in this case.
      * An Iterable of numbers (int or float) that specify the relative width of
        each column. E.g. ``[0.7, 0.3]`` creates two columns where the first
        one takes up 70% of the available with and the second one takes up 30%.
        Or ``[1, 2, 3]`` creates three columns where the second one is two times
        the width of the first one, and the third one is three times that width.
  
  gap : "small", "medium", or "large"
      The size of the gap between the columns. Defaults to "small".
  
  Returns
  -------
  list of containers
      A list of container objects.
  
  Examples
  --------
  You can use `with` notation to insert any element into a column:
  
  >>> import streamlit as st
  >>>
  >>> col1, col2, col3 = st.columns(3)
  >>>
  >>> with col1:
  ...    st.header("A cat")
  ...    st.image("https://static.streamlit.io/examples/cat.jpg")
  ...
  >>> with col2:
  ...    st.header("A dog")
  ...    st.image("https://static.streamlit.io/examples/dog.jpg")
  ...
  >>> with col3:
  ...    st.header("An owl")
  ...    st.image("https://static.streamlit.io/examples/owl.jpg")
  
  .. output ::
      https://doc-columns1.streamlit.app/
      height: 620px
  
  Or you can just call methods directly in the returned objects:
  
  >>> import streamlit as st
  >>> import numpy as np
  >>>
  >>> col1, col2 = st.columns([3, 1])
  >>> data = np.random.randn(10, 1)
  >>>
  >>> col1.subheader("A wide column with a chart")
  >>> col1.line_chart(data)
  >>>
  >>> col2.subheader("A narrow column with the data")
  >>> col2.write(data)
  
  .. output ::
      https://doc-columns2.streamlit.app/
      height: 550px
code: def columns(
      self, spec: SpecType, *, gap: Optional[str] = "small"
  ) -> List["DeltaGenerator"]:
      """Insert containers laid out as side-by-side columns.
  
      Inserts a number of multi-element containers laid out side-by-side and
      returns a list of container objects.
  
      To add elements to the returned containers, you can use "with" notation
      (preferred) or just call methods directly on the returned object. See
      examples below.
  
      Columns can only be placed inside other columns up to one level of nesting.
  
      .. warning::
          Columns cannot be placed inside other columns in the sidebar. This is only possible in the main area of the app.
  
      Parameters
      ----------
      spec : int or Iterable of numbers
          Controls the number and width of columns to insert. Can be one of:
  
          * An integer that specifies the number of columns. All columns have equal
            width in this case.
          * An Iterable of numbers (int or float) that specify the relative width of
            each column. E.g. ``[0.7, 0.3]`` creates two columns where the first
            one takes up 70% of the available with and the second one takes up 30%.
            Or ``[1, 2, 3]`` creates three columns where the second one is two times
            the width of the first one, and the third one is three times that width.
  
      gap : "small", "medium", or "large"
          The size of the gap between the columns. Defaults to "small".
  
      Returns
      -------
      list of containers
          A list of container objects.
  
      Examples
      --------
      You can use `with` notation to insert any element into a column:
  
      >>> import streamlit as st
      >>>
      >>> col1, col2, col3 = st.columns(3)
      >>>
      >>> with col1:
      ...    st.header("A cat")
      ...    st.image("https://static.streamlit.io/examples/cat.jpg")
      ...
      >>> with col2:
      ...    st.header("A dog")
      ...    st.image("https://static.streamlit.io/examples/dog.jpg")
      ...
      >>> with col3:
      ...    st.header("An owl")
      ...    st.image("https://static.streamlit.io/examples/owl.jpg")
  
      .. output ::
          https://doc-columns1.streamlit.app/
          height: 620px
  
      Or you can just call methods directly in the returned objects:
  
      >>> import streamlit as st
      >>> import numpy as np
      >>>
      >>> col1, col2 = st.columns([3, 1])
      >>> data = np.random.randn(10, 1)
      >>>
      >>> col1.subheader("A wide column with a chart")
      >>> col1.line_chart(data)
      >>>
      >>> col2.subheader("A narrow column with the data")
      >>> col2.write(data)
  
      .. output ::
          https://doc-columns2.streamlit.app/
          height: 550px
  
      """
      weights = spec
      weights_exception = StreamlitAPIException(
          "The input argument to st.columns must be either a "
          + "positive integer or a list of positive numeric weights. "
          + "See [documentation](https://docs.streamlit.io/library/api-reference/layout/st.columns) "
          + "for more information."
      )
  
      if isinstance(weights, int):
          # If the user provided a single number, expand into equal weights.
          # E.g. (1,) * 3 => (1, 1, 1)
          # NOTE: A negative/zero spec will expand into an empty tuple.
          weights = (1,) * weights
  
      if len(weights) == 0 or any(weight <= 0 for weight in weights):
          raise weights_exception
  
      def column_gap(gap):
          if type(gap) == str:
              gap_size = gap.lower()
              valid_sizes = ["small", "medium", "large"]
  
              if gap_size in valid_sizes:
                  return gap_size
  
          raise StreamlitAPIException(
              'The gap argument to st.columns must be "small", "medium", or "large". \n'
              f"The argument passed was {gap}."
          )
  
      gap_size = column_gap(gap)
  
      def column_proto(normalized_weight: float) -> BlockProto:
          col_proto = BlockProto()
          col_proto.column.weight = normalized_weight
          col_proto.column.gap = gap_size
          col_proto.allow_empty = True
          return col_proto
  
      block_proto = BlockProto()
      block_proto.horizontal.gap = gap_size
      row = self.dg._block(block_proto)
      total_weight = sum(weights)
      return [
          row._block(column_proto(w / total_weight)) for w in weights
      ]
  
file_path: streamlit/lib/streamlit/elements/layouts.py
imports: from __future__ import annotations
  from typing import TYPE_CHECKING, List, Literal, Optional, Sequence, Union, cast
  from streamlit.errors import StreamlitAPIException
  from streamlit.proto.Block_pb2 import Block
  from streamlit.runtime.metrics_util import gather_metrics
label_desc: Use image node_id 2 for calling the LayoutsMixin obj's underlying member method code with example usage: obj.columns(spec) and returns: unknown, col_proto, gap_size