Skip to content

Commit a5132c3

Browse files
authored
Classes extend BiocObject (#10)
1 parent 155d878 commit a5132c3

File tree

16 files changed

+62
-97
lines changed

16 files changed

+62
-97
lines changed

.github/workflows/run-tests.yml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -28,7 +28,7 @@ jobs:
2828
test:
2929
strategy:
3030
matrix:
31-
python: ["3.9", "3.10", "3.11", "3.12", "3.13"]
31+
python: ["3.10", "3.11", "3.12", "3.13", "3.14"]
3232
platform:
3333
- ubuntu-latest
3434
- macos-latest

CHANGELOG.md

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,10 @@
11
# Changelog
22

3+
## Version 0.4.0
4+
5+
- Classes extend `BiocObject` from biocutils. `metadata` is a named list.
6+
- Update actions to run from 3.10-3.14
7+
38
## Version 0.3.0
49

510
- Renamed `CompressedBiocFrameList` to `CompressedSplitBiocFrameList` since the current implementation can only handle dataframes with the same number and names of columns.

setup.cfg

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -49,9 +49,9 @@ python_requires = >=3.9
4949
# For more information, check out https://semver.org/.
5050
install_requires =
5151
importlib-metadata; python_version<"3.8"
52-
biocutils
52+
biocutils>=0.3.1
5353
numpy
54-
biocframe
54+
biocframe>=0.7.1
5555

5656

5757
[options.packages.find]

src/compressed_lists/base.py

Lines changed: 22 additions & 69 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,6 @@
1-
from typing import Any, Callable, Iterator, List, Optional, Sequence, Union
1+
from __future__ import annotations
2+
3+
from typing import Any, Callable, Dict, Iterator, List, Optional, Sequence, Union
24
from warnings import warn
35

46
import biocutils as ut
@@ -19,7 +21,7 @@ def _validate_data_and_partitions(unlist_data, partition):
1921
)
2022

2123

22-
class CompressedList:
24+
class CompressedList(ut.BiocObject):
2325
"""Base class for compressed list objects.
2426
2527
`CompressedList` stores list elements concatenated in a single vector-like object
@@ -32,8 +34,8 @@ def __init__(
3234
partitioning: Partitioning,
3335
element_type: Any = None,
3436
element_metadata: Optional[dict] = None,
35-
metadata: Optional[dict] = None,
36-
validate: bool = True,
37+
metadata: Optional[Union[Dict[str, Any], ut.NamedList]] = None,
38+
_validate: bool = True,
3739
):
3840
"""Initialize a CompressedList.
3941
@@ -53,24 +55,20 @@ class for the type of elements.
5355
metadata:
5456
Optional general metadata.
5557
56-
validate:
58+
_validate:
5759
Internal use only.
5860
"""
61+
62+
super().__init__(metadata=metadata, _validate=_validate)
63+
5964
self._unlist_data = unlist_data
6065
self._partitioning = partitioning
6166
self._element_type = element_type
6267
self._element_metadata = element_metadata or {}
63-
self._metadata = metadata or {}
6468

65-
if validate:
69+
if _validate:
6670
_validate_data_and_partitions(self._unlist_data, self._partitioning)
6771

68-
def _define_output(self, in_place: bool = False) -> "CompressedList":
69-
if in_place is True:
70-
return self
71-
else:
72-
return self.__copy__()
73-
7472
#########################
7573
######>> Copying <<######
7674
#########################
@@ -219,7 +217,7 @@ def get_names(self) -> Optional[ut.Names]:
219217
"""Get the names of list elements."""
220218
return self._partitioning.get_names()
221219

222-
def set_names(self, names: Sequence[str], in_place: bool = False) -> "CompressedList":
220+
def set_names(self, names: Sequence[str], in_place: bool = False) -> CompressedList:
223221
"""Set the names of list elements.
224222
225223
names:
@@ -263,7 +261,7 @@ def get_unlist_data(self) -> Any:
263261
"""Get all elements."""
264262
return self._unlist_data
265263

266-
def set_unlist_data(self, unlist_data: Any, in_place: bool = False) -> "CompressedList":
264+
def set_unlist_data(self, unlist_data: Any, in_place: bool = False) -> CompressedList:
267265
"""Set new list elements.
268266
269267
Args:
@@ -312,7 +310,7 @@ def get_element_metadata(self) -> dict:
312310
"""
313311
return self._element_metadata
314312

315-
def set_element_metadata(self, element_metadata: dict, in_place: bool = False) -> "CompressedList":
313+
def set_element_metadata(self, element_metadata: dict, in_place: bool = False) -> CompressedList:
316314
"""Set new element metadata.
317315
318316
Args:
@@ -349,54 +347,6 @@ def element_metadata(self, element_metadata: dict):
349347
)
350348
self.set_element_metadata(element_metadata, in_place=True)
351349

352-
###########################
353-
######>> metadata <<#######
354-
###########################
355-
356-
def get_metadata(self) -> dict:
357-
"""
358-
Returns:
359-
Dictionary of metadata for this object.
360-
"""
361-
return self._metadata
362-
363-
def set_metadata(self, metadata: dict, in_place: bool = False) -> "CompressedList":
364-
"""Set additional metadata.
365-
366-
Args:
367-
metadata:
368-
New metadata for this object.
369-
370-
in_place:
371-
Whether to modify the ``CompressedList`` in place.
372-
373-
Returns:
374-
A modified ``CompressedList`` object, either as a copy of the original
375-
or as a reference to the (in-place-modified) original.
376-
"""
377-
if not isinstance(metadata, dict):
378-
raise TypeError(f"`metadata` must be a dictionary, provided {type(metadata)}.")
379-
output = self._define_output(in_place)
380-
output._metadata = metadata
381-
return output
382-
383-
@property
384-
def metadata(self) -> dict:
385-
"""Alias for :py:attr:`~get_metadata`."""
386-
return self.get_metadata()
387-
388-
@metadata.setter
389-
def metadata(self, metadata: dict):
390-
"""Alias for :py:attr:`~set_metadata` with ``in_place = True``.
391-
392-
As this mutates the original object, a warning is raised.
393-
"""
394-
warn(
395-
"Setting property 'metadata' is an in-place operation, use 'set_metadata' instead",
396-
UserWarning,
397-
)
398-
self.set_metadata(metadata, in_place=True)
399-
400350
##########################
401351
######>> accessors <<#####
402352
##########################
@@ -472,8 +422,11 @@ def extract_range(self, start: int, end: int) -> Any:
472422

473423
@classmethod
474424
def from_list(
475-
cls, lst: Any, names: Optional[Union[ut.Names, Sequence[str]]] = None, metadata: Optional[dict] = None
476-
) -> "CompressedList":
425+
cls,
426+
lst: Any,
427+
names: Optional[Union[ut.Names, Sequence[str]]] = None,
428+
metadata: Optional[Union[Dict[str, Any], ut.NamedList]] = None,
429+
) -> CompressedList:
477430
"""Create a CompressedList from a regular list.
478431
479432
This method must be implemented by subclasses to handle
@@ -544,7 +497,7 @@ def unlist(self, use_names: bool = False) -> Any:
544497
else self._unlist_data.set_names(self.get_partitioning().get_names(), in_place=False)
545498
)
546499

547-
def relist(self, unlist_data: Any) -> "CompressedList":
500+
def relist(self, unlist_data: Any) -> CompressedList:
548501
"""Create a new `CompressedList` with the same partitioning but different data.
549502
550503
Args:
@@ -565,7 +518,7 @@ def relist(self, unlist_data: Any) -> "CompressedList":
565518
metadata=self._metadata.copy(),
566519
)
567520

568-
def extract_subset(self, indices: Sequence[int]) -> "CompressedList":
521+
def extract_subset(self, indices: Sequence[int]) -> CompressedList:
569522
"""Extract a subset of elements by indices.
570523
571524
Args:
@@ -608,7 +561,7 @@ def extract_subset(self, indices: Sequence[int]) -> "CompressedList":
608561
metadata=self._metadata.copy(),
609562
)
610563

611-
def lapply(self, func: Callable) -> "CompressedList":
564+
def lapply(self, func: Callable) -> CompressedList:
612565
"""Apply a function to each element.
613566
614567
Args:

src/compressed_lists/biocframe_list.py

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,6 @@
1-
from typing import List, Optional, Sequence, Union
1+
from __future__ import annotations
2+
3+
from typing import Any, Dict, List, Optional, Sequence, Union
24

35
import biocutils as ut
46
from biocframe import BiocFrame
@@ -22,7 +24,7 @@ def __init__(
2224
unlist_data: BiocFrame,
2325
partitioning: Partitioning,
2426
element_metadata: Optional[dict] = None,
25-
metadata: Optional[dict] = None,
27+
metadata: Optional[Union[Dict[str, Any], ut.NamedList]] = None,
2628
**kwargs,
2729
):
2830
"""Initialize a CompressedSplitBiocFrameList.
@@ -56,7 +58,7 @@ def from_list(
5658
lst: List[BiocFrame],
5759
names: Optional[Union[ut.Names, Sequence[str]]] = None,
5860
metadata: Optional[dict] = None,
59-
) -> "CompressedSplitBiocFrameList":
61+
) -> CompressedSplitBiocFrameList:
6062
"""Create a `CompressedSplitBiocFrameList` from a regular list.
6163
6264
This concatenates the list of `BiocFrame` objects.

src/compressed_lists/bool_list.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
from typing import Optional, Sequence, Union
1+
from typing import Any, Dict, Optional, Sequence, Union
22
from warnings import warn
33

44
import biocutils as ut
@@ -20,7 +20,7 @@ def __init__(
2020
unlist_data: ut.BooleanList,
2121
partitioning: Partitioning,
2222
element_metadata: Optional[dict] = None,
23-
metadata: Optional[dict] = None,
23+
metadata: Optional[Union[Dict[str, Any], ut.NamedList]] = None,
2424
**kwargs,
2525
):
2626
"""Initialize a CompressedBooleanList.

src/compressed_lists/float_list.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
from typing import Optional, Sequence, Union
1+
from typing import Any, Dict, Optional, Sequence, Union
22
from warnings import warn
33

44
import biocutils as ut
@@ -20,7 +20,7 @@ def __init__(
2020
unlist_data: ut.FloatList,
2121
partitioning: Partitioning,
2222
element_metadata: Optional[dict] = None,
23-
metadata: Optional[dict] = None,
23+
metadata: Optional[Union[Dict[str, Any], ut.NamedList]] = None,
2424
**kwargs,
2525
):
2626
"""Initialize a CompressedFloatList.

src/compressed_lists/integer_list.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
from typing import Optional, Sequence, Union
1+
from typing import Any, Dict, Optional, Sequence, Union
22
from warnings import warn
33

44
import biocutils as ut
@@ -20,7 +20,7 @@ def __init__(
2020
unlist_data: ut.IntegerList,
2121
partitioning: Partitioning,
2222
element_metadata: Optional[dict] = None,
23-
metadata: Optional[dict] = None,
23+
metadata: Optional[Union[Dict[str, Any], ut.NamedList]] = None,
2424
**kwargs,
2525
):
2626
"""Initialize a CompressedIntegerList.

src/compressed_lists/numpy_list.py

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,6 @@
1-
from typing import List, Optional, Sequence, Union
1+
from __future__ import annotations
2+
3+
from typing import Any, Dict, List, Optional, Sequence, Union
24
from warnings import warn
35

46
import biocutils as ut
@@ -21,7 +23,7 @@ def __init__(
2123
unlist_data: np.ndarray,
2224
partitioning: Partitioning,
2325
element_metadata: Optional[dict] = None,
24-
metadata: Optional[dict] = None,
26+
metadata: Optional[Union[Dict[str, Any], ut.NamedList]] = None,
2527
**kwargs,
2628
):
2729
"""Initialize a CompressedNumpyList.
@@ -63,7 +65,7 @@ def from_list(
6365
lst: List[np.ndarray],
6466
names: Optional[Union[ut.Names, Sequence[str]]] = None,
6567
metadata: Optional[dict] = None,
66-
) -> "CompressedNumpyList":
68+
) -> CompressedNumpyList:
6769
"""
6870
Create a `CompressedNumpyList` from a list of NumPy vectors.
6971

src/compressed_lists/partition.py

Lines changed: 6 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,5 @@
1+
from __future__ import annotations
2+
13
from typing import List, Optional, Sequence, Union
24
from warnings import warn
35

@@ -56,7 +58,7 @@ def __init__(
5658
@classmethod
5759
def from_lengths(
5860
cls, lengths: Sequence[int], names: Optional[Union[ut.Names, Sequence[str]]] = None
59-
) -> "Partitioning":
61+
) -> Partitioning:
6062
"""Create a Partitioning from a sequence of lengths.
6163
6264
Args:
@@ -73,7 +75,7 @@ def from_lengths(
7375
return cls(ends, names)
7476

7577
@classmethod
76-
def from_list(cls, lst: List, names: Optional[Union[ut.Names, Sequence[str]]] = None) -> "Partitioning":
78+
def from_list(cls, lst: List, names: Optional[Union[ut.Names, Sequence[str]]] = None) -> Partitioning:
7779
"""Create a Partitioning from a list by using the lengths of each element.
7880
7981
Args:
@@ -89,7 +91,7 @@ def from_list(cls, lst: List, names: Optional[Union[ut.Names, Sequence[str]]] =
8991
lengths = [len(item) if hasattr(item, "__len__") else 1 for item in lst]
9092
return cls.from_lengths(lengths, names)
9193

92-
def _define_output(self, in_place: bool = False) -> "Partitioning":
94+
def _define_output(self, in_place: bool = False) -> Partitioning:
9395
if in_place is True:
9496
return self
9597
else:
@@ -220,7 +222,7 @@ def get_names(self) -> Optional[ut.Names]:
220222
"""Return the names of each partition."""
221223
return self._names
222224

223-
def set_names(self, names: Optional[Union[ut.Names, Sequence[str]]], in_place: bool = False) -> "Partitioning":
225+
def set_names(self, names: Optional[Union[ut.Names, Sequence[str]]], in_place: bool = False) -> Partitioning:
224226
"""Set the names of list elements.
225227
226228
Args:

0 commit comments

Comments
 (0)