tiled icon indicating copy to clipboard operation
tiled copied to clipboard

Adapter Rationalisation

Open DiamondJoseph opened this issue 5 months ago • 1 comments

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?

DiamondJoseph avatar Aug 06 '25 12:08 DiamondJoseph