Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[python] Add bool to supported types and improve type specification #141

Merged
merged 1 commit into from
Feb 24, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
44 changes: 25 additions & 19 deletions python-spec/src/somacore/options.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@
"""

import enum
from typing import Any, Mapping, Optional, Sequence, Union
from typing import Any, Mapping, Optional, Sequence, TypeVar, Union

import attrs
import numpy as np
Expand Down Expand Up @@ -110,36 +110,42 @@ class ResultOrder(enum.Enum):
ResultOrderStr = Union[ResultOrder, Literal["auto", "row-major", "column-major"]]
"""A ResultOrder, or the str representing it."""


DenseCoord = Union[None, int, types.Slice[int]]
# Coordinate types are specified as TypeVars instead of Unions to ensure that
# sequences and slices are homogeneous:
#
# BadCoord = Union[int, str]
# BadCoords = Union[BadCoord, Sequence[BadCoord]]
# # ["this", 1] is bad, but is a valid as a BadCoords value
#
# GoodCoord = TypeVar("GoodCoord", int, str)
# GoodCoords = Union[GoodCoord, Sequence[GoodCoord]]
# # ["this", 1] is bad, and is *not* valid as a GoodCoords value
# # ["this", "that"] is a valid as a GoodCoords value
# # [1, 2] is valid as a GoodCoords value

DenseCoord = TypeVar("DenseCoord", None, int, types.Slice[int])
"""A single coordinate range for reading dense data.

``None`` indicates the entire domain of a dimension; values of this type are
not ``Optional``, but may be ``None``.
"""


DenseNDCoords = Sequence[DenseCoord]
"""A sequence of ranges to read dense data."""

# TODO: Add support for non-integer types.
SparseCoord = TypeVar(
"SparseCoord", bytes, float, int, slice, str, np.datetime64, pa.TimestampType
)
"""Types that can be put into a single sparse coordinate."""

# NOTE: Keep this in sync with the types accepted in `_canonicalize_coord`
# in ./query/axis.py.
# https://github.com/single-cell-data/TileDB-SOMA/issues/960
SparseDFCoord = Union[
DenseCoord,
float,
np.datetime64,
pa.TimestampType,
Sequence[int],
Sequence[float],
Sequence[str],
Sequence[bytes],
Sequence[np.datetime64],
Sequence[pa.TimestampType],
types.Slice[float],
types.Slice[str],
types.Slice[bytes],
types.Slice[np.datetime64],
types.Slice[pa.TimestampType],
SparseCoord,
Sequence[SparseCoord],
types.Slice[SparseCoord],
pa.Array,
pa.ChunkedArray,
npt.NDArray[np.integer],
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

should we also have a numpy-array-like for np.float, np.datetime64, etc?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is a good idea but I think it makes sense for a future change. (Also, I am not familiar enough with the numpy typing system at the moment to do the right thing here.)

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Expand Down
1 change: 1 addition & 0 deletions python-spec/src/somacore/query/axis.py
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,7 @@ def _canonicalize_coord(coord: options.SparseDFCoord) -> options.SparseDFCoord:
if coord is None or isinstance(
coord,
(
bool,
bytes,
float,
int,
Expand Down
1 change: 1 addition & 0 deletions python-spec/testing/test_query_axis.py
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@
(slice(np.datetime64(946684802, "s"), np.datetime64(946684803, "s")),),
),
(("string-coord", [b"lo", b"hi"]), ("string-coord", (b"lo", b"hi"))),
((slice(4, 5), True, None), (slice(4, 5), True, None)),
],
)
def test_canonicalization(coords: Any, want: Tuple[options.SparseDFCoord, ...]) -> None:
Expand Down