docs: def _read_rec_with_var(
              self, colnums, rows, dtype, offsets, isvar, vstorage):
          """
          Read columns from a table into a rec array, including variable length
          columns.  This is special because, for efficiency, it involves reading
          from the main table as normal but skipping the columns in the array
          that are variable.  Then reading the variable length columns, with
          accounting for strides appropriately.
  
          row and column numbers should be checked before calling this function
          """
  
          colnumsp = colnums+1
          if rows is None:
              nrows = self._info['nrows']
          else:
              nrows = rows.size
          array = numpy.zeros(nrows, dtype=dtype)
  
          # read from the main table first
          wnotvar, = numpy.where(isvar == False)  # noqa
          if wnotvar.size > 0:
              # this will be contiguous (not true for slices)
              thesecol = colnumsp[wnotvar]
              theseoff = offsets[wnotvar]
              self._FITS.read_columns_as_rec_byoffset(self._ext+1,
                                                      thesecol,
                                                      theseoff,
                                                      array,
                                                      rows)
              for i in xrange(thesecol.size):
  
                  name = array.dtype.names[wnotvar[i]]
                  colnum = thesecol[i]-1
                  self._rescale_and_convert_field_inplace(
                      array,
                      name,
                      self._info['colinfo'][colnum]['tscale'],
                      self._info['colinfo'][colnum]['tzero'])
  
          array = self._maybe_decode_fits_ascii_strings_to_unicode_py3(array)
  
          # now read the variable length arrays we may be able to speed this up
          # by storing directly instead of reading first into a list
          wvar, = numpy.where(isvar == True)  # noqa
          if wvar.size > 0:
              # this will be contiguous (not true for slices)
              thesecol = colnumsp[wvar]
              for i in xrange(thesecol.size):
                  colnump = thesecol[i]
                  name = array.dtype.names[wvar[i]]
                  dlist = self._FITS.read_var_column_as_list(
                      self._ext+1, colnump, rows)
  
                  if (isinstance(dlist[0], str) or
                          (IS_PY3 and isinstance(dlist[0], bytes))):
                      is_string = True
                  else:
                      is_string = False
  
                  if array[name].dtype.descr[0][1][1] == 'O':
                      # storing in object array
                      # get references to each, no copy made
                      for irow, item in enumerate(dlist):
                          if IS_PY3 and isinstance(item, bytes):
                              item = item.decode('ascii')
                          array[name][irow] = item
                  else:
                      for irow, item in enumerate(dlist):
                          if IS_PY3 and isinstance(item, bytes):
                              item = item.decode('ascii')
  
                          if is_string:
                              array[name][irow] = item
                          else:
                              ncopy = len(item)
  
                              if IS_PY3:
                                  ts = array[name].dtype.descr[0][1][1]
                                  if ts != 'S' and ts != 'U':
                                      array[name][irow][0:ncopy] = item[:]
                                  else:
                                      array[name][irow] = item
                              else:
                                  array[name][irow][0:ncopy] = item[:]
  
          return array