code: def _get_frame_row_type(dtype):
      """
      Get the Numba type of a row in a frame. Models each column and its mask as
      a MaskedType and models the row as a dictionary like data structure
      containing these MaskedTypes. Large parts of this function are copied with
      comments from the Numba internals and slightly modified to account for
      validity bools to be present in the final struct. See
      numba.np.numpy_support.from_struct_dtype for details.
      """
  
      # Create the numpy structured type corresponding to the numpy dtype.
  
      fields = []
      offset = 0
  
      sizes = [
          _get_extensionty_size(string_view)
          if val[0] == np.dtype("O")
          else val[0].itemsize
          for val in dtype.fields.values()
      ]
  
      for i, (name, info) in enumerate(dtype.fields.items()):
          # *info* consists of the element dtype, its offset from the beginning
          # of the record, and an optional "title" containing metadata.
          # We ignore the offset in info because its value assumes no masking;
          # instead, we compute the correct offset based on the masked type.
          elemdtype = info[0]
          title = info[2] if len(info) == 3 else None
  
          ty = (
              # columns of dtype string start life as string_view
              string_view
              if elemdtype == np.dtype("O")
              else numpy_support.from_dtype(elemdtype)
          )
          infos = {
              "type": MaskedType(ty),
              "offset": offset,
              "title": title,
          }
          fields.append((name, infos))
  
          # increment offset by itemsize plus one byte for validity
          itemsize = (
              _get_extensionty_size(string_view)
              if elemdtype == np.dtype("O")
              else elemdtype.itemsize
          )
          offset += itemsize + 1
  
          # Align the next member of the struct to be a multiple of the
          # memory access size, per PTX ISA 7.4/5.4.5
          if i < len(sizes) - 1:
              next_itemsize = sizes[i + 1]
              offset = int(
                  math.ceil(offset / next_itemsize) * next_itemsize
              )
  
      # Numba requires that structures are aligned for the CUDA target
      _is_aligned_struct = True
      return Row(fields, offset, _is_aligned_struct)
  
file_path: cudf/python/cudf/cudf/core/udf/row_function.py
imports: import math
  import numpy
  from numba import cuda
  from numba.np import numpy_support
  from cudf.core.udf.api import Masked, pack_return
  from cudf.core.udf.masked_typing import MaskedType
  from cudf.core.udf.strings_typing import string_view
  from cudf.core.udf.templates import masked_input_initializer_template, row_initializer_template, row_kernel_template, unmasked_input_initializer_template
  from cudf.core.udf.utils import Row, _all_dtypes_from_frame, _construct_signature, _get_extensionty_size, _get_kernel, _get_udf_return_type, _mask_get, _supported_cols_from_frame, _supported_dtypes_from_frame
label_desc: Use image node_id 1 for calling a global function with example usage: _get_frame_row_type(dtype) and returns: Row