from __future__ import annotations
import numpy as np
import typing_extensions as tp
from numpy.ma import MaskedArray
from static_frame.core.doc_str import doc_inject
from static_frame.core.exception import immutable_type_error_factory
from static_frame.core.util import NULL_SLICE
from static_frame.core.util import TBlocKey
from static_frame.core.util import TCallableAny
from static_frame.core.util import TDepthLevelSpecifier
from static_frame.core.util import TDtypeSpecifier
from static_frame.core.util import TDtypesSpecifier
from static_frame.core.util import TILocSelector
from static_frame.core.util import TILocSelectorCompound
from static_frame.core.util import TILocSelectorMany
from static_frame.core.util import TILocSelectorOne
from static_frame.core.util import TLabel
from static_frame.core.util import TLocSelector
from static_frame.core.util import TLocSelectorCompound
from static_frame.core.util import TLocSelectorMany
# from static_frame.core.util import TCallableAny
if tp.TYPE_CHECKING:
from static_frame.core.assign import Assign # pragma: no cover
from static_frame.core.batch import Batch # pragma: no cover
from static_frame.core.bus import Bus # pragma: no cover
from static_frame.core.frame import Frame # pragma: no cover
from static_frame.core.frame import FrameAssignILoc # #pragma: no cover
from static_frame.core.frame import FrameAsType # pragma: no cover
from static_frame.core.frame import FrameGO # #pragma: no cover
from static_frame.core.frame import FrameHE # #pragma: no cover
from static_frame.core.index import Index # #pragma: no cover
from static_frame.core.index_base import IndexBase # pragma: no cover
from static_frame.core.index_hierarchy import IndexHierarchy # pragma: no cover
from static_frame.core.index_hierarchy import IndexHierarchyAsType # pragma: no cover
from static_frame.core.series import Series # pragma: no cover
from static_frame.core.series import SeriesAssign # #pragma: no cover
from static_frame.core.series import SeriesHE # #pragma: no cover
from static_frame.core.type_blocks import TypeBlocks # #pragma: no cover
from static_frame.core.yarn import Yarn # pragma: no cover
TNDArrayAny = np.ndarray[tp.Any, tp.Any] #pragma: no cover
TDtypeAny = np.dtype[tp.Any] #pragma: no cover
TSeriesAny = Series[tp.Any, tp.Any] #pragma: no cover
TFrameAny = Frame[tp.Any, tp.Any, tp.Unpack[tp.Tuple[tp.Any, ...]]] #pragma: no cover
TBusAny = Bus[tp.Any] #pragma: no cover
TYarnAny = Yarn[tp.Any] #pragma: no cover
#-------------------------------------------------------------------------------
TFrameOrSeries = tp.Union[
'Frame[tp.Any, tp.Any, tp.Unpack[tp.Tuple[tp.Any, ...]]]',
'Series[tp.Any, tp.Any]',
]
TVContainer_co = tp.TypeVar('TVContainer_co',
'Index[tp.Any]',
'Series[tp.Any, tp.Any]',
'SeriesHE[tp.Any, tp.Any]',
'Frame[tp.Any, tp.Any, tp.Unpack[tp.Tuple[tp.Any, ...]]]',
'FrameGO[tp.Any, tp.Any]',
'FrameHE[tp.Any, tp.Any, tp.Unpack[tp.Tuple[tp.Any, ...]]]',
'TypeBlocks',
'Bus[tp.Any]',
'Batch',
'Yarn[tp.Any]',
'IndexHierarchy',
'SeriesAssign',
'FrameAssignILoc',
np.ndarray[tp.Any, tp.Any],
MaskedArray, # type: ignore
TFrameOrSeries,
covariant=True,
)
TVIndex = tp.TypeVar('TVIndex', bound='IndexBase', default=tp.Any)
TVColumns = tp.TypeVar('TVColumns', bound='IndexBase', default=tp.Any)
TLocSelectorFunc = tp.TypeVar('TLocSelectorFunc',
bound=tp.Callable[[TLocSelector], TVContainer_co] # pyright: ignore
)
TILocSelectorFunc = tp.TypeVar('TILocSelectorFunc',
bound=tp.Callable[[TILocSelector], TVContainer_co] # pyright: ignore
)
TLocSelectorFuncInPlace = tp.TypeVar('TLocSelectorFuncInPlace',
bound=tp.Callable[[TLocSelector], None] # pyright: ignore
)
TILocSelectorFuncInPlace = tp.TypeVar('TILocSelectorFuncInPlace',
bound=tp.Callable[[TILocSelector], None] # pyright: ignore
)
TVDtype = tp.TypeVar('TVDtype', bound=np.generic, default=tp.Any)
class Interface:
__slots__ = ()
_INTERFACE: tp.Tuple[str, ...] = ()
class InterfaceBatch:
__slots__ = ()
_INTERFACE: tp.Tuple[str, ...] = ()
class InterGetItemILocReduces(Interface, tp.Generic[TVContainer_co, TVDtype]):
'''Interface for iloc selection that reduces dimensionality.
'''
__slots__ = ('_func',)
_INTERFACE = ('__getitem__',)
def __init__(self, func: tp.Union[
tp.Callable[[TILocSelectorOne], TVDtype],
tp.Callable[[TILocSelectorMany], TVContainer_co]]) -> None:
self._func: tp.Union[
tp.Callable[[TILocSelectorOne], TVDtype],
tp.Callable[[TILocSelectorMany], TVContainer_co]] = func
@tp.overload
def __getitem__(self, key: TILocSelectorMany) -> TVContainer_co: ...
@tp.overload
def __getitem__(self, key: TILocSelectorOne) -> TVDtype: ...
def __getitem__(self, key: TILocSelector) -> tp.Any:
return self._func(key) # type: ignore
def __setitem__(self, key: TLabel, value: tp.Any) -> None:
raise immutable_type_error_factory(self._func.__self__.__class__, 'iloc', key, value) # type: ignore
class InterGetItemILoc(Interface, tp.Generic[TVContainer_co]):
'''Interface for iloc selection that does not reduce dimensionality.
'''
__slots__ = ('_func',)
_INTERFACE = ('__getitem__',)
def __init__(self, func: tp.Union[
tp.Callable[[TILocSelectorOne], tp.Any],
tp.Callable[[TILocSelectorMany], TVContainer_co]]) -> None:
self._func: tp.Union[
tp.Callable[[TILocSelectorOne], tp.Any],
tp.Callable[[TILocSelectorMany], TVContainer_co]] = func
def __getitem__(self, key: TILocSelector) -> TVContainer_co:
return self._func(key) # type: ignore
class InterGetItemILocInPlace(Interface, tp.Generic[TVContainer_co]):
'''Variant that has None return.
'''
__slots__ = ('_func',)
_INTERFACE = ('__getitem__',)
def __init__(self, func: tp.Union[
tp.Callable[[TILocSelectorOne], None],
tp.Callable[[TILocSelectorMany], None]]) -> None:
self._func = func
def __getitem__(self, key: TILocSelector) -> None:
self._func(key) # type: ignore
class InterGetItemLocReduces(Interface, tp.Generic[TVContainer_co, TVDtype]):
__slots__ = ('_func',)
_INTERFACE = ('__getitem__',)
_func: tp.Callable[[TLocSelector], TVContainer_co]
def __init__(self,
func: tp.Callable[[TLocSelector], TVContainer_co],
) -> None:
self._func = func
@tp.overload
def __getitem__(self, key: TLocSelectorMany) -> TVContainer_co: ...
@tp.overload
def __getitem__(self, key: TLabel) -> TVDtype: ...
def __getitem__(self, key: TLocSelector) -> tp.Any:
return self._func(key)
def __setitem__(self, key: TLabel, value: tp.Any) -> None:
raise immutable_type_error_factory(self._func.__self__.__class__, 'loc', key, value) # type: ignore
class InterGetItemLoc(Interface, tp.Generic[TVContainer_co]):
__slots__ = ('_func',)
_INTERFACE = ('__getitem__',)
_func: tp.Callable[[TLocSelector], TVContainer_co]
def __init__(self, func: tp.Callable[[TLocSelector], TVContainer_co]) -> None:
self._func = func
def __getitem__(self, key: TLocSelector) -> TVContainer_co:
return self._func(key)
class InterGetItemLocInPlace(Interface, tp.Generic[TVContainer_co]):
'''Variant that has None return.
'''
__slots__ = ('_func',)
_INTERFACE = ('__getitem__',)
_func: tp.Callable[[TLocSelector], None]
def __init__(self, func: tp.Callable[[TLocSelector], None]) -> None:
self._func = func
def __getitem__(self, key: TLocSelector) -> None:
self._func(key)
class InterGetItemLocCompoundReduces(Interface,
tp.Generic[TVContainer_co, TVIndex, TVColumns]):
'''Interface for compound loc selection that reduces dimensionality. TVContainer_co is the outermost container
'''
__slots__ = ('_func',)
_INTERFACE = ('__getitem__',)
_func: tp.Callable[[TLocSelectorCompound], tp.Any]
def __init__(self, func: tp.Callable[[TLocSelectorCompound], tp.Any]) -> None:
self._func = func
@tp.overload
def __getitem__(self, key: tp.Tuple[slice, slice]) -> TVContainer_co: ...
@tp.overload # selects a Series as a row
def __getitem__(self, key: tp.Tuple[TLabel, TLocSelectorMany]) -> Series[TVColumns, tp.Any]: ...
@tp.overload # selects a Series as s column
def __getitem__(self, key: tp.Tuple[TLocSelectorMany, TLabel]) -> Series[TVIndex, tp.Any]: ...
@tp.overload
def __getitem__(self, key: tp.Tuple[tp.List[int], tp.List[int]]) -> TVContainer_co: ...
@tp.overload
def __getitem__(self, key: tp.Tuple[tp.List[str], tp.List[str]]) -> TVContainer_co: ...
@tp.overload
def __getitem__(self, key: tp.Tuple[TLocSelectorMany, TLocSelectorMany]) -> TVContainer_co: ...
@tp.overload
def __getitem__(self, key: tp.Tuple[TLabel, TLabel]) -> tp.Any: ...
@tp.overload
def __getitem__(self, key: TLabel) -> TSeriesAny: ...
@tp.overload
def __getitem__(self, key: TLocSelectorMany) -> TVContainer_co: ...
@tp.overload
def __getitem__(self, key: TLocSelectorCompound) -> tp.Any: ...
def __getitem__(self, key: TLocSelectorCompound) -> tp.Any:
return self._func(key)
def __setitem__(self, key: TLabel, value: tp.Any) -> None:
raise immutable_type_error_factory(self._func.__self__.__class__, 'loc', key, value) # type: ignore
class InterGetItemLocCompound(Interface, tp.Generic[TVContainer_co]):
'''Interface for compound loc selection that does not reduce dimensionality. TVContainer_co is the only delivered container container
'''
__slots__ = ('_func',)
_INTERFACE = ('__getitem__',)
_func: tp.Callable[[TLocSelectorCompound], TVContainer_co]
def __init__(self, func: tp.Callable[[TLocSelectorCompound], TVContainer_co]) -> None:
self._func = func
def __getitem__(self, key: TLocSelectorCompound) -> TVContainer_co:
return self._func(key)
def __setitem__(self, key: TLabel, value: tp.Any) -> None:
raise immutable_type_error_factory(self._func.__self__.__class__, 'loc', key, value) # type: ignore
class InterGetItemILocCompoundReduces(Interface, tp.Generic[TVContainer_co]):
__slots__ = ('_func',)
_INTERFACE = ('__getitem__',)
_func: tp.Callable[[TILocSelectorCompound], tp.Any]
def __init__(self, func: tp.Callable[[TILocSelectorCompound], tp.Any]) -> None:
self._func = func
@tp.overload
def __getitem__(self, key: TILocSelectorOne) -> TSeriesAny: ...
@tp.overload
def __getitem__(self, key: TILocSelectorMany) -> TVContainer_co: ...
@tp.overload
def __getitem__(self, key: tp.Tuple[TILocSelectorOne, TILocSelectorMany]) -> TSeriesAny: ...
@tp.overload
def __getitem__(self, key: tp.Tuple[TILocSelectorMany, TILocSelectorOne]) -> TSeriesAny: ...
@tp.overload
def __getitem__(self, key: tp.Tuple[TILocSelectorMany, TILocSelectorMany]) -> TVContainer_co: ...
@tp.overload
def __getitem__(self, key: tp.Tuple[TILocSelectorOne, TILocSelectorOne]) -> tp.Any: ...
@tp.overload
def __getitem__(self, key: TILocSelectorMany) -> TVContainer_co: ...
@tp.overload
def __getitem__(self, key: TILocSelectorCompound) -> tp.Any: ...
def __getitem__(self, key: TILocSelectorCompound) -> tp.Any:
return self._func(key)
def __setitem__(self, key: TLabel, value: tp.Any) -> None:
raise immutable_type_error_factory(self._func.__self__.__class__, 'iloc', key, value)# type: ignore
class InterGetItemILocCompound(Interface, tp.Generic[TVContainer_co]):
__slots__ = ('_func',)
_INTERFACE = ('__getitem__',)
_func: tp.Callable[[TILocSelectorCompound], TVContainer_co]
def __init__(self, func: tp.Callable[[TILocSelectorCompound], TVContainer_co]) -> None:
self._func = func
def __getitem__(self, key: TILocSelectorCompound) -> TVContainer_co:
return self._func(key)
def __setitem__(self, key: TLabel, value: tp.Any) -> None:
raise immutable_type_error_factory(self._func.__self__.__class__, 'loc', key, value) # type: ignore
class InterfaceGetItemBLoc(Interface, tp.Generic[TVContainer_co]):
__slots__ = ('_func',)
_INTERFACE = ('__getitem__',)
_func: tp.Callable[[TBlocKey], TVContainer_co]
def __init__(self, func: tp.Callable[[TBlocKey], TVContainer_co]) -> None:
self._func = func
def __getitem__(self, key: TBlocKey) -> TVContainer_co:
return self._func(key)
#-------------------------------------------------------------------------------
class InterfaceSelectDuo(Interface, tp.Generic[TVContainer_co]):
'''An instance to serve as an interface to all of iloc and loc
'''
__slots__ = (
'_func_iloc',
'_func_loc',
)
_INTERFACE = ('iloc', 'loc')
def __init__(self, *,
func_iloc: TILocSelectorFunc,
func_loc: TLocSelectorFunc) -> None:
self._func_iloc = func_iloc
self._func_loc = func_loc
@property
def iloc(self) -> InterGetItemILocReduces[TVContainer_co, tp.Any]:
return InterGetItemILocReduces(self._func_iloc)
@property
def loc(self) -> InterGetItemLocReduces[TVContainer_co, tp.Any]:
return InterGetItemLocReduces(self._func_loc) # pyright: ignore
class InterfaceSelectTrio(Interface, tp.Generic[TVContainer_co]):
'''An instance to serve as an interface to all of iloc, loc, and __getitem__ extractors. It is assumed that functionality that uses this interface returns containers that do not reduce their dimensionality.
'''
__slots__ = (
'_func_iloc',
'_func_loc',
'_func_getitem',
)
_INTERFACE = ('__getitem__', 'iloc', 'loc')
def __init__(self, *,
func_iloc: TILocSelectorFunc,
func_loc: TLocSelectorFunc,
func_getitem: TLocSelectorFunc,
) -> None:
self._func_iloc = func_iloc
self._func_loc = func_loc
self._func_getitem = func_getitem
[docs]
def __getitem__(self, key: TLocSelector) -> tp.Any:
'''Label-based selection.
'''
return self._func_getitem(key)
@property
def iloc(self) -> InterGetItemILoc[TVContainer_co]:
'''Integer-position based selection.'''
return InterGetItemILoc(self._func_iloc)
@property
def loc(self) -> InterGetItemLoc[TVContainer_co]:
'''Label-based selection.
'''
return InterGetItemLoc(self._func_loc) # pyright: ignore
class InterfaceSelectQuartet(Interface, tp.Generic[TVContainer_co]):
'''An instance to serve as an interface to all of iloc, loc, and __getitem__ extractors.
'''
__slots__ = (
'_func_iloc',
'_func_loc',
'_func_getitem',
'_func_bloc',
)
_INTERFACE = ('__getitem__', 'iloc', 'loc', 'bloc')
def __init__(self, *,
func_iloc: TILocSelectorFunc,
func_loc: TLocSelectorFunc,
func_getitem: TLocSelectorFunc,
func_bloc: tp.Any, # not sure what is the right type
) -> None:
self._func_iloc = func_iloc
self._func_loc = func_loc
self._func_getitem = func_getitem
self._func_bloc = func_bloc
def __getitem__(self, key: TLocSelector) -> tp.Any:
'''Label-based selection.
'''
return self._func_getitem(key)
@property
def bloc(self) -> InterGetItemLocReduces[TVContainer_co, tp.Any]:
'''Boolean based assignment.'''
return InterGetItemLocReduces(self._func_bloc)
@property
def iloc(self) -> InterGetItemILocReduces[TVContainer_co, tp.Any]:
'''Integer-position based assignment.'''
return InterGetItemILocReduces(self._func_iloc)
@property
def loc(self) -> InterGetItemLocReduces[TVContainer_co, tp.Any]:
'''Label-based assignment.
'''
return InterGetItemLocReduces(self._func_loc) # pyright: ignore
#-------------------------------------------------------------------------------
class InterfaceAssignTrio(InterfaceSelectTrio[TVContainer_co]):
'''For assignment with __getitem__, iloc, loc.
'''
__slots__ = ('delegate',)
def __init__(self, *,
func_iloc: TILocSelectorFunc,
func_loc: TLocSelectorFunc,
func_getitem: TLocSelectorFunc,
delegate: tp.Type[Assign]
) -> None:
InterfaceSelectTrio.__init__(self,
func_iloc=func_iloc,
func_loc=func_loc,
func_getitem=func_getitem,
)
self.delegate = delegate
class InterfaceAssignQuartet(InterfaceSelectQuartet[TVContainer_co]):
'''For assignment with __getitem__, iloc, loc, bloc.
'''
__slots__ = ('delegate',)
def __init__(self, *,
func_iloc: TILocSelectorFunc,
func_loc: TLocSelectorFunc,
func_getitem: TLocSelectorFunc,
func_bloc: tp.Any, # not sure what is the right type
delegate: tp.Type[Assign]
) -> None:
InterfaceSelectQuartet.__init__(self,
func_iloc=func_iloc,
func_loc=func_loc,
func_getitem=func_getitem,
func_bloc=func_bloc,
)
self.delegate = delegate
#-------------------------------------------------------------------------------
class InterfaceFrameAsType(Interface, tp.Generic[TVContainer_co]):
__slots__ = ('_func_getitem',)
_INTERFACE = ('__getitem__', '__call__')
def __init__(self,
func_getitem: tp.Callable[[TLocSelector], 'FrameAsType']
) -> None:
'''
Args:
_func_getitem: a callable that expects a _func_getitem key and returns a FrameAsType interface; for example, Frame._extract_getitem_astype.
'''
self._func_getitem = func_getitem
[docs]
@doc_inject(selector='selector')
def __getitem__(self, key: TLocSelector) -> 'FrameAsType':
'''Selector of columns by label.
Args:
key: {key_loc}
'''
return self._func_getitem(key)
[docs]
def __call__(self,
dtype: TDtypeSpecifier,
*,
consolidate_blocks: bool = False,
) -> TFrameAny:
'''
Apply a single ``dtype`` to all columns.
'''
return self._func_getitem(NULL_SLICE)(
dtype,
consolidate_blocks=consolidate_blocks,
)
class InterfacePersist(Interface, tp.Generic[TVContainer_co]):
__slots__ = (
'_func_iloc',
'_func_loc',
'_func_getitem',
)
_INTERFACE = ('__getitem__', 'iloc', 'loc', '__call__')
def __init__(self, *,
func_iloc: TILocSelectorFuncInPlace,
func_loc: TLocSelectorFuncInPlace,
func_getitem: TLocSelectorFuncInPlace,
) -> None:
self._func_iloc = func_iloc
self._func_loc = func_loc
self._func_getitem = func_getitem
def __getitem__(self, key: TLocSelector) -> None:
'''Label-based selection.
'''
self._func_getitem(key)
@property
def iloc(self) -> InterGetItemILocInPlace[TVContainer_co]:
'''Integer-position based selection.'''
return InterGetItemILocInPlace(self._func_iloc)
@property
def loc(self) -> InterGetItemLocInPlace[TVContainer_co]:
'''Label-based selection.
'''
return InterGetItemLocInPlace(self._func_loc) # pyright: ignore
def __call__(self) -> None:
'''
Persist all `Frame`.
'''
self._func_getitem(NULL_SLICE)
class InterfaceIndexHierarchyAsType(Interface, tp.Generic[TVContainer_co]):
__slots__ = ('_func_getitem',)
_INTERFACE = ('__getitem__', '__call__')
def __init__(self,
func_getitem: tp.Callable[[TDepthLevelSpecifier], 'IndexHierarchyAsType']
) -> None:
'''
Args:
_func_getitem: a callable that expects a _func_getitem key and returns a IndexHierarchyAsType interface; for example, Frame._extract_getitem_astype.
'''
self._func_getitem = func_getitem
[docs]
@doc_inject(selector='selector')
def __getitem__(self, key: TDepthLevelSpecifier) -> 'IndexHierarchyAsType':
'''Selector of columns by label.
Args:
key: {key_loc}
'''
return self._func_getitem(key)
[docs]
def __call__(self,
dtype: TDtypeAny,
*,
consolidate_blocks: bool = False,
) -> 'IndexHierarchy':
'''
Apply a single ``dtype`` to all columns.
'''
return self._func_getitem(NULL_SLICE)(
dtype,
consolidate_blocks=consolidate_blocks,
)
class BatchAsType:
__slots__ = ('_batch_apply', '_column_key')
def __init__(self,
batch_apply: tp.Callable[[TCallableAny], 'Batch'],
column_key: TLocSelector
) -> None:
self._batch_apply = batch_apply
self._column_key = column_key
def __call__(self,
dtypes: TDtypesSpecifier,
*,
consolidate_blocks: bool = False,
) -> 'Batch':
return self._batch_apply(
lambda c: c.astype[self._column_key](
dtypes,
consolidate_blocks=consolidate_blocks,
)
)
class InterfaceBatchAsType(Interface, tp.Generic[TVContainer_co]):
'''An instance to serve as an interface to __getitem__ extractors. Used by both :obj:`Frame` and :obj:`IndexHierarchy`.
'''
__slots__ = ('_batch_apply',)
_INTERFACE = ('__getitem__', '__call__')
def __init__(self,
batch_apply: tp.Callable[[TCallableAny], 'Batch'],
) -> None:
self._batch_apply = batch_apply
[docs]
@doc_inject(selector='selector')
def __getitem__(self, key: TLocSelector) -> BatchAsType:
'''Selector of columns by label.
Args:
key: {key_loc}
'''
return BatchAsType(batch_apply=self._batch_apply, column_key=key)
[docs]
def __call__(self, dtype: TDtypeAny) -> 'Batch':
'''
Apply a single ``dtype`` to all columns.
'''
return BatchAsType(
batch_apply=self._batch_apply,
column_key=NULL_SLICE,
)(dtype)
#-------------------------------------------------------------------------------
class InterfaceConsolidate(Interface, tp.Generic[TVContainer_co]):
'''An instance to serve as an interface to __getitem__ extractors.
'''
__slots__ = (
'_container',
'_func_getitem',
)
_INTERFACE = (
'__getitem__',
'__call__',
'status',
)
def __init__(self,
container: TVContainer_co,
func_getitem: tp.Callable[[TLocSelector], TFrameAny]
) -> None:
'''
Args:
_func_getitem: a callable that expects a _func_getitem key and returns a Frame interface.
'''
self._container: TVContainer_co = container
self._func_getitem = func_getitem
[docs]
@doc_inject(selector='selector')
def __getitem__(self, key: TLocSelector) -> TFrameAny:
'''Return the full ``Frame``, selecting with ``key`` a subset of columns for consolidation.
Args:
key: {key_loc}
'''
return self._func_getitem(key)
[docs]
def __call__(self) -> TFrameAny:
'''
Apply consolidation to all columns.
'''
return self._func_getitem(NULL_SLICE)
@property
def status(self) -> TFrameAny:
'''Display consolidation status of this Frame.
'''
from static_frame.core.frame import Frame
flag_attrs: tp.Tuple[str, ...] = ('owndata', 'f_contiguous', 'c_contiguous')
columns: IndexBase = self._container.columns # type: ignore
def gen() -> tp.Iterator[tp.Sequence[tp.Any]]:
iloc_start = 0
for b in self._container._blocks._blocks: # type: ignore
width = 1 if b.ndim == 1 else b.shape[1]
iloc_end = iloc_start + width
if iloc_end >= len(columns):
iloc_slice = slice(iloc_start, None)
else:
iloc_slice = slice(iloc_start, iloc_end)
sub = columns[iloc_slice] # returns a column
iloc: tp.Union[int, slice]
if len(sub) == 1:
loc = sub[0]
iloc = iloc_start
else: # get inclusive slice
loc = slice(sub[0], sub[-1])
iloc = iloc_slice
yield [loc, iloc, b.dtype, b.shape, b.ndim] + [
getattr(b.flags, attr) for attr in flag_attrs]
iloc_start = iloc_end
return Frame.from_records(gen(),
columns=('loc', 'iloc', 'dtype', 'shape', 'ndim') + flag_attrs
)