Adapter Rationalisation
An Adapter adapts a/many particular mimetype[s] to a single StructureFamily and syntax of access, e.g. an ArrayAdapter regardless of its backing can be indexed and sliced.
A TableAdapter can be accessed like a table, with string keys (table headers) accessing columns of data (ArrayAdapters)
A ContainerAdapter contains other adapters and has a string keys for accessing them.
Is a TableAdapter just a special case of ContainerAdapter[Adapter[ArrayStructure]] where all the Arrays are 1-dimensional and have the same length?
DatasetAdapter(MapAdapter) has a StructureFamily of Container but otherwise is very similar to a TableAdapter, which implies that again there may be something to gain here.
Proposed Structures:
@dataclass
class ShapedStructure: # new
chunks: Tuple[Tuple[int, ...], ...]
shape: Tuple[int, ...]
resizable: Union[bool, Tuple[bool, ...]] = False
# validator to ensure shape, chunks, resizable are same length
# Remove `dims` key
@dataclass
class ArrayStructure(ShapedStructure):
data_type: Union[BuiltinDtype, StructDtype]
@dataclass
class AwkwardStructure:
length: int
form: dict
@dataclass
class SparseStructure(ShapedStructure):
dims: Optional[Tuple[str, ...]] = None # Should these, like Arrays in Tables, belong to the containing ContainerAdapter?
layout: SparseLayout
# if dims is set, must be same length as Shape?
@dataclass
class ArrowStructure(TableStructure):
arrow_schema: str
npartitions: int
@dataclass
class ContainerStructure(Generic[E]): #new
keys: List[E]
@dataclass
class TableStructure(ContainerStructure[str]): # columns -> keys
resizable: Union[bool, Tuple[bool, ...]] = False
And Adapters:
class Adapter(Protocol, Generic[T]):
@abstractmethod
def structure(self) -> T:
pass
A = TypeVar("A", bound=Adapter[Any])
class ContainerAdapter(Adapter[ContainerStructure[K]], Mapping[K, A], Generic[K, A]):
class MapAdapter(ContainerAdapter[str, Adapter[A]], Generic[A]):
class TableAdapter(MapAdapter[Adapter[ArrayStructure]]):
class ArrayAdapter(Adapter[ArrayStructure]):
class HDF5ArrayAdapter(ArrayAdapter):
class ZarrArrayAdapter(ArrayAdapter):
class JPEGAdapter(Adapter[ArrayStructure]): # Can this be refactored to (ArrayAdapter)?
class TiffAdapter(Adapter[ArrayStructure]): # Can this be refactored to (ArrayAdapter)?
class NPYAdapter(Adapter[ArrayStructure]): # Can this be refactored to (ArrayAdapter)?
class FileSequenceAdapter(Adapter[ArrayStructure]):
class NPYSequenceAdapter(FileSequenceAdapter):
class TiffSequenceAdapter(FileSequenceAdapter):
class ArrowAdapter(Adapter[ArrowStructure]): # Can this be refactored to (TableAdapter)?
class ParquetDatasetAdapter(TableAdapter): # Only overwrites `write`?
class CSVAdapter(MapAdapter[TableAdapter]):
class ExcelAdapter(MapAdapter[TableAdapter]): # Possibly (CSVAdapter)?
class HDF5Adapter(TableAdapter[HDF5Adapter | HDF5ArrayAdapter]):
class ZarrGroupAdapter(MapAdapter[ArrayAdapter | ZarrGroupAdapter]):
class SQLAdapter(TableAdapter): # common behaviour for all SQL adapters
class PerUniqueHeadersSQLAdapter(SQLAdapter): # current behaviour
# TODO: #1053 class OneBigTableSQLAdapter(SQLAdapter):
class AwkwardAdapter(Adapter[AwkwardStructure]):
class AwkwardBuffersAdapter(AwkwardAdapter):
class COOAdapter(Adapter[SparseStructure]):
class SparseBlocksParquetAdapter(COOAdapter):
# Remove
class NetCDFAdapter: # Defers to TableAdapter
class DatasetAdapter(MapAdapter): # Is a TableAdapter?
class DirectoryContainer(Mapping[str, bytes]): # - why is this under Adapters?
root_node (and nodes for directories) are then just MapAdapter[Adapter[Any]].
DLS may need to extend MapAdapter for our files and folders with the same names #1014?