From 104ca685f1a484110ed73d266c5e1b0145521662 Mon Sep 17 00:00:00 2001 From: "pre-commit-ci[bot]" <66853113+pre-commit-ci[bot]@users.noreply.github.com> Date: Mon, 17 Aug 2026 16:31:41 +0000 Subject: [PATCH 1/2] [pre-commit.ci] pre-commit autoupdate MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit updates: - [github.com/astral-sh/ruff-pre-commit: v0.15.6 → v0.16.3](https://github.com/astral-sh/ruff-pre-commit/compare/v0.15.6...v0.16.3) --- .pre-commit-config.yaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml index 3f91485..303c3c5 100644 --- a/.pre-commit-config.yaml +++ b/.pre-commit-config.yaml @@ -33,7 +33,7 @@ repos: - repo: https://github.com/astral-sh/ruff-pre-commit # Ruff version. - rev: v0.15.6 + rev: v0.16.3 hooks: - id: ruff args: [--fix, --exit-non-zero-on-fix] From b558145615f8248ac81d9d6fb2b532cc4a5ab429 Mon Sep 17 00:00:00 2001 From: "pre-commit-ci[bot]" <66853113+pre-commit-ci[bot]@users.noreply.github.com> Date: Mon, 17 Aug 2026 16:31:49 +0000 Subject: [PATCH 2/2] [pre-commit.ci] auto fixes from pre-commit.com hooks for more information, see https://pre-commit.ci --- setup.py | 2 +- src/biocutils/BooleanList.py | 13 +++--- src/biocutils/Factor.py | 34 +++++++-------- src/biocutils/FloatList.py | 13 +++--- src/biocutils/IntegerList.py | 13 +++--- src/biocutils/NamedList.py | 41 +++++++++--------- src/biocutils/Names.py | 25 ++++++----- src/biocutils/StringList.py | 13 +++--- src/biocutils/__init__.py | 65 ++++++++++++---------------- src/biocutils/assign.py | 3 +- src/biocutils/assign_rows.py | 3 +- src/biocutils/assign_sequence.py | 5 ++- src/biocutils/biocobject.py | 8 ++-- src/biocutils/duplicated.py | 11 +++-- src/biocutils/factorize.py | 10 ++--- src/biocutils/intersect.py | 2 +- src/biocutils/is_list_of_type.py | 6 +-- src/biocutils/map_to_index.py | 3 +- src/biocutils/match.py | 21 ++++----- src/biocutils/normalize_subscript.py | 7 +-- src/biocutils/order.py | 15 ++++--- src/biocutils/package_utils.py | 2 - src/biocutils/print_truncated.py | 10 ++--- src/biocutils/print_wrapped_table.py | 18 ++++---- src/biocutils/reverse_index.py | 2 +- src/biocutils/show_as_cell.py | 5 ++- src/biocutils/split.py | 7 +-- src/biocutils/subset.py | 3 +- src/biocutils/subset_rows.py | 3 +- src/biocutils/subset_sequence.py | 5 ++- src/biocutils/table.py | 2 +- src/biocutils/union.py | 2 +- src/biocutils/which.py | 4 +- 33 files changed, 190 insertions(+), 186 deletions(-) diff --git a/setup.py b/setup.py index 4fbfd79..d0f5a68 100644 --- a/setup.py +++ b/setup.py @@ -10,7 +10,7 @@ if __name__ == "__main__": try: setup(use_scm_version={"version_scheme": "no-guess-dev"}) - except: # noqa + except: print( "\n\nAn error occurred while building the project, " "please ensure you have the most updated version of setuptools, " diff --git a/src/biocutils/BooleanList.py b/src/biocutils/BooleanList.py index 12a32f7..67b0a64 100644 --- a/src/biocutils/BooleanList.py +++ b/src/biocutils/BooleanList.py @@ -1,6 +1,7 @@ from __future__ import annotations -from typing import Any, Iterable, Optional, Sequence, Union +from collections.abc import Iterable, Sequence +from typing import Any from .NamedList import NamedList from .Names import Names @@ -23,7 +24,7 @@ def __init__(self, data: Sequence) -> None: """ self._data = data - def __getitem__(self, index: int) -> Optional[bool]: + def __getitem__(self, index: int) -> bool | None: """Get an item and coerce it to boolean. Args: @@ -46,8 +47,8 @@ class BooleanList(NamedList): def __init__( self, - data: Optional[Sequence] = None, - names: Optional[Names] = None, + data: Sequence | None = None, + names: Names | None = None, _validate: bool = True, ): """ @@ -76,7 +77,7 @@ def __init__( super().__init__(data, names, _validate=_validate) - def set_value(self, index: Union[int, str], value: Any, in_place: bool = False) -> BooleanList: + def set_value(self, index: int | str, value: Any, in_place: bool = False) -> BooleanList: """Calls :py:meth:`~biocutils.NamedList.NamedList.set_value` after coercing ``value`` to a boolean.""" return super().set_value(index, _coerce_to_bool(value), in_place=in_place) @@ -84,7 +85,7 @@ def set_slice(self, index: SubscriptTypes, value: Sequence, in_place: bool = Fal """Calls :py:meth:`~biocutils.NamedList.NamedList.set_slice` after coercing ``value`` to booleans.""" return super().set_slice(index, _SubscriptCoercer(value), in_place=in_place) - def safe_insert(self, index: Union[int, str], value: Any, in_place: bool = False) -> BooleanList: + def safe_insert(self, index: int | str, value: Any, in_place: bool = False) -> BooleanList: """Calls :py:meth:`~biocutils.NamedList.NamedList.safe_insert` after coercing ``value`` to a boolean.""" return super().safe_insert(index, _coerce_to_bool(value), in_place=in_place) diff --git a/src/biocutils/Factor.py b/src/biocutils/Factor.py index 7162cf7..537da35 100644 --- a/src/biocutils/Factor.py +++ b/src/biocutils/Factor.py @@ -1,8 +1,8 @@ from __future__ import annotations import warnings +from collections.abc import Sequence from copy import copy, deepcopy -from typing import Optional, Sequence, Union import numpy @@ -78,7 +78,7 @@ def __iter__(self) -> FactorIterator: """ return self - def __next__(self) -> Union[str, None]: + def __next__(self) -> str | None: """ Returns: Level corresponding to the code at the current position, or None @@ -102,10 +102,10 @@ class Factor: def __init__( self, - codes: Union[numpy.ndarray, Sequence[int]], - levels: Union[StringList, Sequence[str]], + codes: numpy.ndarray | Sequence[int], + levels: StringList | Sequence[str], ordered: bool = False, - names: Optional[Union[Names, Sequence[str]]] = None, + names: Names | Sequence[str] | None = None, _validate: bool = True, ): """Initialize a Factor object. @@ -246,7 +246,7 @@ def names(self) -> Names: """Alias for :py:meth:`~get_names`.""" return self.get_names() - def set_names(self, names: Optional[Names], in_place: bool = False) -> "NamedList": + def set_names(self, names: Names | None, in_place: bool = False) -> NamedList: """ Args: names: @@ -341,7 +341,7 @@ def __eq__(self, other: Factor): #####>>>> Slicing <<<<##### ########################### - def get_value(self, index: Union[str, int]) -> Union[str, None]: + def get_value(self, index: str | int) -> str | None: """ Args: index: @@ -380,7 +380,7 @@ def get_slice(self, index: SubscriptTypes) -> Factor: output._names = subset_sequence(self._names, index) return output - def __getitem__(self, index: SubscriptTypes) -> Union[str, Factor]: + def __getitem__(self, index: SubscriptTypes) -> str | Factor: """ If ``index`` is a scalar, this is an alias for :py:meth:`~get_value`. @@ -392,7 +392,7 @@ def __getitem__(self, index: SubscriptTypes) -> Union[str, Factor]: else: return self.get_slice(NormalizedSubscript(index)) - def set_value(self, index: Union[str, int], value: Union[str, None], in_place: bool = False) -> Factor: + def set_value(self, index: str | int, value: str | None, in_place: bool = False) -> Factor: """ Args: index: @@ -482,7 +482,7 @@ def set_slice(self, index: SubscriptTypes, value: Factor, in_place: bool = False return output - def __setitem__(self, index: SubscriptTypes, value: Union[str, Factor]): + def __setitem__(self, index: SubscriptTypes, value: str | Factor): """ If ``index`` is a scalar, this is an alias for :py:meth:`~set_value`. @@ -588,7 +588,7 @@ def replace_levels( output._levels = new_levels return output - def set_levels(self, levels: Union[str, Sequence[str]], remap: bool = True, in_place: bool = False) -> Factor: + def set_levels(self, levels: str | Sequence[str], remap: bool = True, in_place: bool = False) -> Factor: """ Alias for :py:meth:`~remap_levels` if ``remap = True``, otherwise an alias for :py:meth:`~replace_levels`. The first alias is deprecated and @@ -600,7 +600,7 @@ def set_levels(self, levels: Union[str, Sequence[str]], remap: bool = True, in_p else: return self.replace_levels(levels, in_place=in_place) - def remap_levels(self, levels: Union[str, Sequence[str]], in_place: bool = False) -> Factor: + def remap_levels(self, levels: str | Sequence[str], in_place: bool = False) -> Factor: """Remap codes to a replacement list of levels. Each entry of the remapped ``Factor`` will refer to the same string across the old and new levels, provided that string is present in both sets of levels. @@ -723,10 +723,10 @@ def to_pandas(self): @staticmethod def from_sequence( x: Sequence[str], - levels: Optional[Sequence[str]] = None, + levels: Sequence[str] | None = None, sort_levels: bool = True, ordered: bool = False, - names: Optional[Sequence[str]] = None, + names: Sequence[str] | None = None, **kwargs, ) -> Factor: """Convert a sequence of hashable values into a factor. @@ -776,7 +776,7 @@ def as_list(self) -> list: """ return [self._levels[c] if c >= 0 else None for c in self._codes] - def safe_delete(self, index: Union[int, str, slice], in_place: bool = False) -> Factor: + def safe_delete(self, index: int | str | slice, in_place: bool = False) -> Factor: """ Args: index: @@ -810,11 +810,11 @@ def safe_delete(self, index: Union[int, str, slice], in_place: bool = False) -> return output - def delete(self, index: Union[int, str, slice]): + def delete(self, index: int | str | slice): """Alias for :py:meth:`~safe_delete` with ``in_place = True``.""" self.safe_delete(index, in_place=True) - def __delitem__(self, index: Union[int, str, slice]): + def __delitem__(self, index: int | str | slice): """Alias for :py:meth:`~delete`.""" self.delete(index) diff --git a/src/biocutils/FloatList.py b/src/biocutils/FloatList.py index 5ddd4cc..417c62e 100644 --- a/src/biocutils/FloatList.py +++ b/src/biocutils/FloatList.py @@ -1,6 +1,7 @@ from __future__ import annotations -from typing import Any, Iterable, Optional, Sequence, Union +from collections.abc import Iterable, Sequence +from typing import Any from .NamedList import NamedList from .Names import Names @@ -27,7 +28,7 @@ def __init__(self, data: Sequence) -> None: """ self._data = data - def __getitem__(self, index: int) -> Optional[float]: + def __getitem__(self, index: int) -> float | None: """Get an item and coerce it to float. Args: @@ -49,8 +50,8 @@ class FloatList(NamedList): def __init__( self, - data: Optional[Sequence] = None, - names: Optional[Names] = None, + data: Sequence | None = None, + names: Names | None = None, _validate: bool = True, ): """ @@ -79,7 +80,7 @@ def __init__( super().__init__(data, names, _validate=_validate) - def set_value(self, index: Union[int, str], value: Any, in_place: bool = False) -> FloatList: + def set_value(self, index: int | str, value: Any, in_place: bool = False) -> FloatList: """Calls :py:meth:`~biocutils.NamedList.NamedList.set_value` after coercing ``value`` to a float.""" return super().set_value(index, _coerce_to_float(value), in_place=in_place) @@ -87,7 +88,7 @@ def set_slice(self, index: SubscriptTypes, value: Sequence, in_place: bool = Fal """Calls :py:meth:`~biocutils.NamedList.NamedList.set_slice` after coercing ``value`` to floats.""" return super().set_slice(index, _SubscriptCoercer(value), in_place=in_place) - def safe_insert(self, index: Union[int, str], value: Any, in_place: bool = False) -> FloatList: + def safe_insert(self, index: int | str, value: Any, in_place: bool = False) -> FloatList: """Calls :py:meth:`~biocutils.NamedList.NamedList.safe_insert` after coercing ``value`` to a float.""" return super().safe_insert(index, _coerce_to_float(value), in_place=in_place) diff --git a/src/biocutils/IntegerList.py b/src/biocutils/IntegerList.py index a88e726..68ca0cd 100644 --- a/src/biocutils/IntegerList.py +++ b/src/biocutils/IntegerList.py @@ -1,6 +1,7 @@ from __future__ import annotations -from typing import Any, Iterable, Optional, Sequence, Union +from collections.abc import Iterable, Sequence +from typing import Any from .NamedList import NamedList from .Names import Names @@ -28,7 +29,7 @@ def __init__(self, data: Sequence) -> None: """ self._data = data - def __getitem__(self, index: int) -> Optional[int]: + def __getitem__(self, index: int) -> int | None: """Get an item and coerce it to integer. Args: @@ -51,8 +52,8 @@ class IntegerList(NamedList): def __init__( self, - data: Optional[Sequence] = None, - names: Optional[Names] = None, + data: Sequence | None = None, + names: Names | None = None, _validate: bool = True, ): """ @@ -80,7 +81,7 @@ def __init__( data = list(_coerce_to_int(item) for item in original) super().__init__(data, names, _validate=_validate) - def set_value(self, index: Union[int, str], value: Any, in_place: bool = False) -> IntegerList: + def set_value(self, index: int | str, value: Any, in_place: bool = False) -> IntegerList: """Calls :py:meth:`~biocutils.NamedList.NamedList.set_value` after coercing ``value`` to a integer.""" return super().set_value(index, _coerce_to_int(value), in_place=in_place) @@ -88,7 +89,7 @@ def set_slice(self, index: SubscriptTypes, value: Sequence, in_place: bool = Fal """Calls :py:meth:`~biocutils.NamedList.NamedList.set_slice` after coercing ``value`` to integers.""" return super().set_slice(index, _SubscriptCoercer(value), in_place=in_place) - def safe_insert(self, index: Union[int, str], value: Any, in_place: bool = False) -> IntegerList: + def safe_insert(self, index: int | str, value: Any, in_place: bool = False) -> IntegerList: """Calls :py:meth:`~biocutils.NamedList.NamedList.safe_insert` after coercing ``value`` to a integer.""" return super().safe_insert(index, _coerce_to_int(value), in_place=in_place) diff --git a/src/biocutils/NamedList.py b/src/biocutils/NamedList.py index d421924..fc0cb95 100644 --- a/src/biocutils/NamedList.py +++ b/src/biocutils/NamedList.py @@ -1,7 +1,8 @@ from __future__ import annotations +from collections.abc import Iterable, Sequence from copy import deepcopy -from typing import Any, Dict, Iterable, Optional, Sequence, Tuple, Union +from typing import Any from .assign_sequence import assign_sequence from .combine_sequences import combine_sequences @@ -23,8 +24,8 @@ class NamedList: def __init__( self, - data: Optional[Sequence] = None, - names: Optional[Names] = None, + data: Sequence | None = None, + names: Names | None = None, _validate: bool = True, ): """ @@ -68,7 +69,7 @@ def __len__(self) -> int: """ return len(self._data) - def __iter__(self) -> "list_iterator": + def __iter__(self) -> list_iterator: """ Returns: An iterator on the underlying list of data. @@ -114,7 +115,7 @@ def __eq__(self, other: NamedList) -> bool: #####>>>> Get/set names <<<<##### ################################# - def get_names(self) -> Optional[Names]: + def get_names(self) -> Names | None: """ Returns: Names for the list elements. @@ -125,14 +126,14 @@ def get_names(self) -> Optional[Names]: return self._names @property - def names(self) -> Optional[Names]: + def names(self) -> Names | None: """Alias for :py:meth:`~get_names`.""" return self.get_names() def _shallow_copy(self): return type(self)(self._data, self._names, _validate=False) - def set_names(self, names: Optional[Names], in_place: bool = False) -> NamedList: + def set_names(self, names: Names | None, in_place: bool = False) -> NamedList: """ Args: names: @@ -153,7 +154,7 @@ def set_names(self, names: Optional[Names], in_place: bool = False) -> NamedList output._names = _sanitize_names(names, len(self)) return output - def get_name(self, index: int) -> Optional[str]: + def get_name(self, index: int) -> str | None: """Get name at an index. Args: @@ -171,7 +172,7 @@ def get_name(self, index: int) -> Optional[str]: #####>>>> Get/set items <<<<##### ################################# - def get_value(self, index: Union[str, int]) -> Any: + def get_value(self, index: str | int) -> Any: """Get value at an index. Args: @@ -207,7 +208,7 @@ def get_slice(self, index: SubscriptTypes) -> NamedList: outnames = subset_sequence(self._names, index) return type(self)(outdata, outnames, _validate=False) - def __getitem__(self, index: SubscriptTypes) -> Union[NamedList, Any]: + def __getitem__(self, index: SubscriptTypes) -> NamedList | Any: """ If ``index`` is a scalar, this is an alias for :py:meth:`~get_value`. @@ -219,7 +220,7 @@ def __getitem__(self, index: SubscriptTypes) -> Union[NamedList, Any]: else: return self.get_slice(NormalizedSubscript(index)) - def set_value(self, index: Union[str, int], value: Any, in_place: bool = False) -> NamedList: + def set_value(self, index: str | int, value: Any, in_place: bool = False) -> NamedList: """ Args: index: @@ -335,7 +336,7 @@ def _define_output(self, in_place: bool) -> NamedList: else: return self.copy() - def safe_insert(self, index: Union[int, str], value: Any, in_place: bool = False) -> NamedList: + def safe_insert(self, index: int | str, value: Any, in_place: bool = False) -> NamedList: """ Args: index: @@ -363,7 +364,7 @@ def safe_insert(self, index: Union[int, str], value: Any, in_place: bool = False output._names.insert(index, "") return output - def insert(self, index: Union[int, str], value: Any): + def insert(self, index: int | str, value: Any): """Alias for :py:meth:`~safe_insert` with ``in_place = True``.""" self.safe_insert(index, value, in_place=True) @@ -435,7 +436,7 @@ def __iadd__(self, other: list): self.extend(other) return self - def safe_delete(self, index: Union[int, str, slice], in_place: bool = False) -> NamedList: + def safe_delete(self, index: int | str | slice, in_place: bool = False) -> NamedList: """ Args: index: @@ -468,11 +469,11 @@ def safe_delete(self, index: Union[int, str, slice], in_place: bool = False) -> return output - def delete(self, index: Union[int, str, slice]): + def delete(self, index: int | str | slice): """Alias for :py:meth:`~safe_delete` with ``in_place = True``.""" self.safe_delete(index, in_place=True) - def __delitem__(self, index: Union[int, str, slice]): + def __delitem__(self, index: int | str | slice): """Alias for :py:meth:`~delete`.""" self.delete(index) @@ -496,7 +497,7 @@ def values(self) -> Iterable[Any]: """ return iter(self._data) - def items(self) -> Iterable[Tuple[str, Any]]: + def items(self) -> Iterable[tuple[str, Any]]: """ Returns: Iterator over (name, value) pairs. @@ -507,7 +508,7 @@ def items(self) -> Iterable[Tuple[str, Any]]: else: return zip((str(i) for i in range(len(self))), self._data) - def get(self, key: Union[str, int], default: Any = None) -> Any: + def get(self, key: str | int, default: Any = None) -> Any: """ Args: key: @@ -576,7 +577,7 @@ def as_list(self) -> list: """ return self._data - def as_dict(self) -> Dict[str, Any]: + def as_dict(self) -> dict[str, Any]: """ Returns: A dictionary where the keys are the names and the values are the @@ -611,7 +612,7 @@ def from_dict(cls, x: dict) -> NamedList: A instance where the list elements are the values of ``x`` and the names are the stringified keys. """ - return cls(list(x.values()), names=Names(str(y) for y in x.keys())) + return cls(list(x.values()), names=Names(str(y) for y in x)) @subset_sequence.register diff --git a/src/biocutils/Names.py b/src/biocutils/Names.py index 1047f79..f869175 100644 --- a/src/biocutils/Names.py +++ b/src/biocutils/Names.py @@ -1,7 +1,8 @@ from __future__ import annotations +from collections.abc import Callable, Iterable, Sequence from copy import deepcopy -from typing import Any, Callable, Iterable, List, Optional, Sequence, Union +from typing import Any, Union from .assign_sequence import assign_sequence from .combine_sequences import combine_sequences @@ -18,7 +19,7 @@ class Names: such that callers can get or set elements by name instead of position. """ - def __init__(self, names: Optional[Iterable] = None, _validate: bool = True): + def __init__(self, names: Iterable | None = None, _validate: bool = True): """ Args: names: @@ -63,7 +64,7 @@ def __len__(self) -> int: """ return len(self._names) - def __iter__(self) -> "list_iterator": + def __iter__(self) -> list_iterator: """ Returns: An iterator on the underlying list of names. @@ -96,7 +97,7 @@ def __eq__(self, other: Names) -> bool: return False return self._names == other._names - def as_list(self) -> List[str]: + def as_list(self) -> list[str]: """ Returns: List of strings containing the names. @@ -160,7 +161,7 @@ def get_slice(self, index: SubscriptTypes) -> Names: index, scalar = normalize_subscript(index, len(self), None) return type(self)(subset_sequence(self._names, index), _validate=False) - def __getitem__(self, index: SubscriptTypes) -> Union[str, Names]: + def __getitem__(self, index: SubscriptTypes) -> str | Names: """ If ``index`` is a scalar, this is an alias for :py:attr:`~get_value`. @@ -339,7 +340,7 @@ def __iadd__(self, other: list): self.extend(other) return self - def safe_delete(self, index: Union[int, slice], in_place: bool = False) -> Names: + def safe_delete(self, index: int | slice, in_place: bool = False) -> Names: """ Args: index: @@ -360,11 +361,11 @@ def safe_delete(self, index: Union[int, slice], in_place: bool = False) -> Names del output._names[index] return output - def delete(self, index: Union[int, slice]): + def delete(self, index: int | slice): """Alias for :py:attr:`~safe_delete` with ``in_place = True``.""" self.safe_delete(index, in_place=True) - def __delitem__(self, index: Union[int, slice]): + def __delitem__(self, index: int | slice): """Alias for :py:attr:`~delete`.""" self.delete(index) @@ -427,7 +428,7 @@ def _combine_sequences_Names(*x: Names) -> Names: return output -def _name_to_position(names: Optional[Names], index: str) -> int: +def _name_to_position(names: Names | None, index: str) -> int: i = -1 if names is not None: i = names.map(index) @@ -436,14 +437,14 @@ def _name_to_position(names: Optional[Names], index: str) -> int: return i -def _validate_names(names: Optional[Names], length: int) -> bool: +def _validate_names(names: Names | None, length: int) -> bool: if names is not None and len(names) != length: raise ValueError("length of 'names' must be equal to number of entries (" + str(length) + ")") return True -def _sanitize_names(names: Optional[Names], length: int) -> Optional[Names]: +def _sanitize_names(names: Names | None, length: int) -> Names | None: if names is None: return names if not isinstance(names, Names): @@ -453,7 +454,7 @@ def _sanitize_names(names: Optional[Names], length: int) -> Optional[Names]: return names -def _combine_names(*x: Any, get_names: Callable) -> Optional[Names]: +def _combine_names(*x: Any, get_names: Callable) -> Names | None: all_names = [] has_names = False for y in x: diff --git a/src/biocutils/StringList.py b/src/biocutils/StringList.py index dee7f17..95a34e3 100644 --- a/src/biocutils/StringList.py +++ b/src/biocutils/StringList.py @@ -1,6 +1,7 @@ from __future__ import annotations -from typing import Any, Iterable, Optional, Sequence, Union +from collections.abc import Iterable, Sequence +from typing import Any from .NamedList import NamedList from .Names import Names @@ -22,7 +23,7 @@ def __init__(self, data: Sequence) -> None: """ self._data = data - def __getitem__(self, index: int) -> Optional[str]: + def __getitem__(self, index: int) -> str | None: """Get an item and coerce it to string. Args: @@ -44,8 +45,8 @@ class StringList(NamedList): def __init__( self, - data: Optional[Sequence] = None, - names: Optional[Names] = None, + data: Sequence | None = None, + names: Names | None = None, _validate: bool = True, ): """ @@ -73,7 +74,7 @@ def __init__( data = list(_coerce_to_str(item) for item in original) super().__init__(data, names, _validate=_validate) - def set_value(self, index: Union[int, str], value: Any, in_place: bool = False) -> StringList: + def set_value(self, index: int | str, value: Any, in_place: bool = False) -> StringList: """Calls :py:meth:`~biocutils.NamedList.NamedList.set_value` after coercing ``value`` to a string.""" return super().set_value(index, _coerce_to_str(value), in_place=in_place) @@ -81,7 +82,7 @@ def set_slice(self, index: SubscriptTypes, value: Sequence, in_place: bool = Fal """Calls :py:meth:`~biocutils.NamedList.NamedList.set_slice` after coercing ``value`` to strings.""" return super().set_slice(index, _SubscriptCoercer(value), in_place=in_place) - def safe_insert(self, index: Union[int, str], value: Any, in_place: bool = False) -> StringList: + def safe_insert(self, index: int | str, value: Any, in_place: bool = False) -> StringList: """Calls :py:meth:`~biocutils.NamedList.NamedList.safe_insert` after coercing ``value`` to a string.""" return super().safe_insert(index, _coerce_to_str(value), in_place=in_place) diff --git a/src/biocutils/__init__.py b/src/biocutils/__init__.py index 61ae709..fb97379 100644 --- a/src/biocutils/__init__.py +++ b/src/biocutils/__init__.py @@ -15,55 +15,44 @@ finally: del version, PackageNotFoundError -from .Factor import Factor -from .StringList import StringList -from .IntegerList import IntegerList -from .FloatList import FloatList +from .assign import assign +from .assign_rows import assign_rows +from .assign_sequence import assign_sequence +from .biocobject import BiocObject from .BooleanList import BooleanList -from .Names import Names -from .NamedList import NamedList - +from .combine import combine +from .combine_columns import combine_columns +from .combine_rows import combine_rows +from .combine_sequences import combine_sequences +from .convert_to_dense import convert_to_dense +from .duplicated import duplicated, unique +from .extract_column_names import extract_column_names +from .extract_row_names import extract_row_names +from .Factor import Factor from .factorize import factorize +from .FloatList import FloatList +from .get_height import get_height +from .IntegerList import IntegerList from .intersect import intersect +from .is_high_dimensional import is_high_dimensional from .is_list_of_type import is_list_of_type from .is_missing_scalar import is_missing_scalar from .map_to_index import map_to_index -from .match import match, create_match_index, MatchIndex -from .normalize_subscript import normalize_subscript, SubscriptTypes +from .match import MatchIndex, create_match_index, match +from .NamedList import NamedList +from .Names import Names +from .normalize_subscript import SubscriptTypes, normalize_subscript +from .order import order, sort from .print_truncated import print_truncated, print_truncated_dict, print_truncated_list from .print_wrapped_table import create_floating_names, print_type, print_wrapped_table, truncate_strings -from .union import union - -from .combine import combine -from .combine_rows import combine_rows -from .combine_columns import combine_columns -from .combine_sequences import combine_sequences - from .relaxed_combine_columns import relaxed_combine_columns from .relaxed_combine_rows import relaxed_combine_rows - -from .extract_row_names import extract_row_names -from .extract_column_names import extract_column_names - +from .show_as_cell import show_as_cell +from .split import split +from .StringList import StringList from .subset import subset from .subset_rows import subset_rows from .subset_sequence import subset_sequence - -from .which import which - -from .assign import assign -from .assign_rows import assign_rows -from .assign_sequence import assign_sequence - -from .show_as_cell import show_as_cell -from .convert_to_dense import convert_to_dense - -from .get_height import get_height -from .is_high_dimensional import is_high_dimensional - -from .biocobject import BiocObject from .table import table - -from .order import order, sort -from .duplicated import duplicated, unique -from .split import split +from .union import union +from .which import which diff --git a/src/biocutils/assign.py b/src/biocutils/assign.py index 875033d..abe8add 100644 --- a/src/biocutils/assign.py +++ b/src/biocutils/assign.py @@ -1,4 +1,5 @@ -from typing import Any, Sequence +from collections.abc import Sequence +from typing import Any from .assign_rows import assign_rows from .assign_sequence import assign_sequence diff --git a/src/biocutils/assign_rows.py b/src/biocutils/assign_rows.py index ada797b..7c4e146 100644 --- a/src/biocutils/assign_rows.py +++ b/src/biocutils/assign_rows.py @@ -1,6 +1,7 @@ +from collections.abc import Sequence from copy import deepcopy from functools import singledispatch -from typing import Any, Sequence +from typing import Any import numpy diff --git a/src/biocutils/assign_sequence.py b/src/biocutils/assign_sequence.py index d6b23d8..cd73d24 100644 --- a/src/biocutils/assign_sequence.py +++ b/src/biocutils/assign_sequence.py @@ -1,6 +1,7 @@ +from collections.abc import Sequence from copy import deepcopy from functools import singledispatch -from typing import Any, Sequence, Union +from typing import Any import numpy @@ -48,7 +49,7 @@ def _assign_sequence_numpy(x: numpy.ndarray, indices: Sequence[int], replacement @assign_sequence.register -def _assign_sequence_range(x: range, indices: Sequence[int], replacement: Any) -> Union[range, list]: +def _assign_sequence_range(x: range, indices: Sequence[int], replacement: Any) -> range | list: if ( isinstance(replacement, range) and isinstance(indices, range) diff --git a/src/biocutils/biocobject.py b/src/biocutils/biocobject.py index 422b7a6..5d17fad 100644 --- a/src/biocutils/biocobject.py +++ b/src/biocutils/biocobject.py @@ -1,7 +1,7 @@ from __future__ import annotations import copy -from typing import Any, Dict, Optional, Union +from typing import Any from warnings import warn from .NamedList import NamedList @@ -40,7 +40,7 @@ class BiocObject: Provides a standardized `metadata` slot and copy-on-write semantics. """ - def __init__(self, metadata: Optional[Union[Dict[str, Any], NamedList]] = None, _validate: bool = True) -> None: + def __init__(self, metadata: dict[str, Any] | NamedList | None = None, _validate: bool = True) -> None: """Initialize the BiocObject. Args: @@ -82,7 +82,7 @@ def metadata(self) -> NamedList: return self._metadata @metadata.setter - def metadata(self, metadata: Optional[Union[Dict[str, Any], NamedList]]) -> None: + def metadata(self, metadata: dict[str, Any] | NamedList | None) -> None: """Set metadata in-place.""" warn( "Setting property 'metadata' is an in-place operation, use 'set_metadata' instead", @@ -94,7 +94,7 @@ def get_metadata(self) -> NamedList: """Alias for :py:attr:`~metadata` getter.""" return self.metadata - def set_metadata(self, metadata: Optional[Union[Dict[str, Any], NamedList]], in_place: bool = False) -> BiocObject: + def set_metadata(self, metadata: dict[str, Any] | NamedList | None, in_place: bool = False) -> BiocObject: """Set new metadata. Args: diff --git a/src/biocutils/duplicated.py b/src/biocutils/duplicated.py index 303af2a..8202cea 100644 --- a/src/biocutils/duplicated.py +++ b/src/biocutils/duplicated.py @@ -1,5 +1,6 @@ +from collections.abc import Sequence from functools import singledispatch -from typing import Any, Sequence, Union +from typing import Any import numpy @@ -8,7 +9,7 @@ @singledispatch -def duplicated(x: Any, incomparables: Union[set, Sequence] = set(), from_last: bool = False) -> numpy.ndarray: +def duplicated(x: Any, incomparables: set | Sequence = set(), from_last: bool = False) -> numpy.ndarray: """ Find duplicated elements of ``x``. @@ -101,9 +102,7 @@ def process(i, y): @duplicated.register -def _duplicated_Factor( - x: Factor, incomparables: Union[set, Sequence] = set(), from_last: bool = False -) -> numpy.ndarray: +def _duplicated_Factor(x: Factor, incomparables: set | Sequence = set(), from_last: bool = False) -> numpy.ndarray: present = [] for lev in x.get_levels(): if lev in incomparables: @@ -140,7 +139,7 @@ def process(i, y): return output -def unique(x: Any, incomparables: Union[set, Sequence] = set(), from_last: bool = False) -> Any: +def unique(x: Any, incomparables: set | Sequence = set(), from_last: bool = False) -> Any: """ Get all unique values of ``x``. diff --git a/src/biocutils/factorize.py b/src/biocutils/factorize.py index 904d24d..b1ef2dd 100644 --- a/src/biocutils/factorize.py +++ b/src/biocutils/factorize.py @@ -1,4 +1,4 @@ -from typing import Optional, Sequence, Tuple +from collections.abc import Sequence import numpy @@ -8,11 +8,11 @@ def factorize( x: Sequence, - levels: Optional[Sequence] = None, + levels: Sequence | None = None, sort_levels: bool = False, - dtype: Optional[numpy.dtype] = None, - fail_missing: Optional[bool] = None, -) -> Tuple[list, numpy.ndarray]: + dtype: numpy.dtype | None = None, + fail_missing: bool | None = None, +) -> tuple[list, numpy.ndarray]: """Convert a sequence of hashable values into a factor. Args: diff --git a/src/biocutils/intersect.py b/src/biocutils/intersect.py index f441492..7b0f5cf 100644 --- a/src/biocutils/intersect.py +++ b/src/biocutils/intersect.py @@ -1,4 +1,4 @@ -from typing import Sequence +from collections.abc import Sequence from .is_missing_scalar import is_missing_scalar from .map_to_index import DUPLICATE_METHOD diff --git a/src/biocutils/is_list_of_type.py b/src/biocutils/is_list_of_type.py index 5f0ff54..1410fe0 100644 --- a/src/biocutils/is_list_of_type.py +++ b/src/biocutils/is_list_of_type.py @@ -1,14 +1,14 @@ -from typing import Callable, Union +from collections.abc import Callable import numpy as np -import numpy.ma as ma +from numpy import ma __author__ = "jkanche" __copyright__ = "jkanche" __license__ = "MIT" -def is_list_of_type(x: Union[list, tuple], target_type: Callable, ignore_none: bool = False) -> bool: +def is_list_of_type(x: list | tuple, target_type: Callable, ignore_none: bool = False) -> bool: """Checks if ``x`` is a list, and whether all elements of the list are of the same type. Args: diff --git a/src/biocutils/map_to_index.py b/src/biocutils/map_to_index.py index fc50b6d..22eca0f 100644 --- a/src/biocutils/map_to_index.py +++ b/src/biocutils/map_to_index.py @@ -1,4 +1,5 @@ -from typing import Literal, Sequence +from collections.abc import Sequence +from typing import Literal from .is_missing_scalar import is_missing_scalar diff --git a/src/biocutils/match.py b/src/biocutils/match.py index 1ebaaf1..b9a60cc 100644 --- a/src/biocutils/match.py +++ b/src/biocutils/match.py @@ -1,5 +1,6 @@ +from collections.abc import Sequence from functools import singledispatch -from typing import Any, Literal, Optional, Sequence, Union +from typing import Any, Literal import numpy @@ -14,9 +15,9 @@ def __init__( self, targets: Any, duplicate_method: Literal["first", "last", "any"] = "first", - incomparables: Union[set, Sequence] = set(), - dtype: Optional[numpy.dtype] = None, - fail_missing: Optional[bool] = None, + incomparables: set | Sequence = set(), + dtype: numpy.dtype | None = None, + fail_missing: bool | None = None, ): """ Args: @@ -141,9 +142,9 @@ def match(self, x: Any) -> numpy.ndarray: def create_match_index( targets: Any, duplicate_method: Literal["first", "last", "any"] = "first", - incomparables: Union[set, Sequence] = set(), - dtype: Optional[numpy.dtype] = None, - fail_missing: Optional[bool] = None, + incomparables: set | Sequence = set(), + dtype: numpy.dtype | None = None, + fail_missing: bool | None = None, ) -> MatchIndex: """ Create a index for matching an arbitrary sequence against ``targets``. @@ -229,9 +230,9 @@ def match( x: Any, targets: Any, duplicate_method: Literal["first", "last", "any"] = "first", - incomparables: Union[set, Sequence] = set(), - dtype: Optional[numpy.dtype] = None, - fail_missing: Optional[bool] = None, + incomparables: set | Sequence = set(), + dtype: numpy.dtype | None = None, + fail_missing: bool | None = None, ) -> numpy.ndarray: """ Find a matching value of each element of ``x`` in ``targets``. diff --git a/src/biocutils/normalize_subscript.py b/src/biocutils/normalize_subscript.py index e41bb92..f9ad762 100644 --- a/src/biocutils/normalize_subscript.py +++ b/src/biocutils/normalize_subscript.py @@ -1,4 +1,5 @@ -from typing import Any, Optional, Sequence, Tuple, Union +from collections.abc import Sequence +from typing import Any, Union import numpy @@ -63,9 +64,9 @@ def __len__(self) -> int: def normalize_subscript( sub: SubscriptTypes, length: int, - names: Optional[Sequence[str]] = None, + names: Sequence[str] | None = None, non_negative_only: bool = True, -) -> Tuple[Sequence[int], bool]: +) -> tuple[Sequence[int], bool]: """Normalize a subscript into a sequence of integer indices. Normalize a subscript for ``__getitem__`` or friends into a sequence of diff --git a/src/biocutils/order.py b/src/biocutils/order.py index dacefca..17f9581 100644 --- a/src/biocutils/order.py +++ b/src/biocutils/order.py @@ -1,18 +1,19 @@ -from typing import Any, Union, Sequence, Optional +from collections.abc import Sequence from functools import singledispatch +from typing import Any import numpy -from .subset import subset from .Factor import Factor +from .subset import subset @singledispatch def order( x: Any, - force_last: Union[set, Sequence] = [None, numpy.ma.masked, numpy.nan], + force_last: set | Sequence = [None, numpy.ma.masked, numpy.nan], decreasing: bool = False, - dtype: Optional[numpy.dtype] = None, + dtype: numpy.dtype | None = None, ) -> numpy.ndarray: """ Obtain an ordering of entries of ``x``. @@ -150,9 +151,9 @@ def key(i): @order.register def _order_Factor( x: Factor, - force_last: Union[set, Sequence] = set([None]), + force_last: set | Sequence = set([None]), decreasing: bool = False, - dtype: Optional[numpy.dtype] = None, + dtype: numpy.dtype | None = None, ) -> numpy.ndarray: new_force_last = set() for i, lev in enumerate(x.get_levels()): @@ -166,7 +167,7 @@ def _order_Factor( @singledispatch -def sort(x: Any, force_last: Union[set, Sequence] = [None, numpy.ma.masked], decreasing: bool = False) -> Any: +def sort(x: Any, force_last: set | Sequence = [None, numpy.ma.masked], decreasing: bool = False) -> Any: """ Sort an arbitrary iterable sequence. diff --git a/src/biocutils/package_utils.py b/src/biocutils/package_utils.py index 55238e5..1f01bdc 100644 --- a/src/biocutils/package_utils.py +++ b/src/biocutils/package_utils.py @@ -21,6 +21,4 @@ def is_package_installed(package_name: str, verbose: bool = False) -> bool: if verbose: print(f"Package '{package_name}' is not installed.") - pass - return _installed diff --git a/src/biocutils/print_truncated.py b/src/biocutils/print_truncated.py index 11b529a..d2b1018 100644 --- a/src/biocutils/print_truncated.py +++ b/src/biocutils/print_truncated.py @@ -1,4 +1,4 @@ -from typing import Callable, Dict, List, Optional +from collections.abc import Callable def print_truncated(x, truncated_to: int = 3, full_threshold: int = 10) -> str: @@ -28,10 +28,10 @@ def print_truncated(x, truncated_to: int = 3, full_threshold: int = 10) -> str: def print_truncated_list( - x: List, + x: list, truncated_to: int = 3, full_threshold: int = 10, - transform: Optional[Callable] = None, + transform: Callable | None = None, sep: str = ", ", include_brackets: bool = True, ) -> str: @@ -87,10 +87,10 @@ def transform(y): def print_truncated_dict( - x: Dict, + x: dict, truncated_to: int = 3, full_threshold: int = 10, - transform: Optional[Callable] = None, + transform: Callable | None = None, sep: str = ", ", include_brackets: bool = True, ) -> str: diff --git a/src/biocutils/print_wrapped_table.py b/src/biocutils/print_wrapped_table.py index 447c8e7..20173f6 100644 --- a/src/biocutils/print_wrapped_table.py +++ b/src/biocutils/print_wrapped_table.py @@ -1,23 +1,23 @@ -from typing import Any, List, Optional, Sequence +from collections.abc import Sequence +from typing import Any import numpy from .subset_sequence import subset_sequence -def _get_max_width(col: List[str]): +def _get_max_width(col: list[str]): width = 0 for y in col: - if len(y) > width: - width = len(y) + width = max(width, len(y)) return width def print_wrapped_table( - columns: List[Sequence[str]], - floating_names: Optional[Sequence[str]] = None, + columns: list[Sequence[str]], + floating_names: Sequence[str] | None = None, sep: str = " ", - window: Optional[int] = None, + window: int | None = None, ) -> str: """Pretty-print a table with aligned and wrapped columns. All column contents are padded so that they are right- justified. Wrapping is performed whenever a new column would exceed the window width, in which case the entire @@ -102,7 +102,7 @@ def reinitialize(): return output -def create_floating_names(names: Optional[List[str]], indices: Sequence[int]) -> List[str]: +def create_floating_names(names: list[str] | None, indices: Sequence[int]) -> list[str]: """Create the floating names to use in :py:meth:`~print_wrapped_table`. If no names are present, positional indices are used instead. @@ -122,7 +122,7 @@ def create_floating_names(names: Optional[List[str]], indices: Sequence[int]) -> return ["[" + str(i) + "]" for i in indices] -def truncate_strings(values: List[str], width: int = 40) -> List[str]: +def truncate_strings(values: list[str], width: int = 40) -> list[str]: """Truncate long strings for printing in :py:meth:`~print_wrapped_table`. Args: diff --git a/src/biocutils/reverse_index.py b/src/biocutils/reverse_index.py index 4d1f2e0..e930711 100644 --- a/src/biocutils/reverse_index.py +++ b/src/biocutils/reverse_index.py @@ -1,4 +1,4 @@ -from typing import Sequence +from collections.abc import Sequence def build_reverse_index(obj: Sequence[str]) -> dict: diff --git a/src/biocutils/show_as_cell.py b/src/biocutils/show_as_cell.py index 072c17f..5c4f3fb 100644 --- a/src/biocutils/show_as_cell.py +++ b/src/biocutils/show_as_cell.py @@ -1,9 +1,10 @@ +from collections.abc import Sequence from functools import singledispatch -from typing import Any, List, Sequence +from typing import Any @singledispatch -def show_as_cell(x: Any, indices: Sequence[int]) -> List[str]: +def show_as_cell(x: Any, indices: Sequence[int]) -> list[str]: """ Show the contents of ``x`` as a cell of a table, typically for use in the ``__str__`` method of a class that contains ``x``. diff --git a/src/biocutils/split.py b/src/biocutils/split.py index 20bb769..ccb24b5 100644 --- a/src/biocutils/split.py +++ b/src/biocutils/split.py @@ -1,5 +1,6 @@ +from collections.abc import Sequence from functools import singledispatch -from typing import Any, Sequence, Union +from typing import Any import numpy @@ -14,10 +15,10 @@ def split( x: Any, f: Sequence, - skip: Union[set, Sequence] = [None, numpy.ma.masked], + skip: set | Sequence = [None, numpy.ma.masked], drop: bool = False, as_NamedList: bool = False, -) -> Union[dict, NamedList]: +) -> dict | NamedList: """ Split a sequence ``x`` into groups defined by a categorical factor ``f``. diff --git a/src/biocutils/subset.py b/src/biocutils/subset.py index 7ef1260..3363a4c 100644 --- a/src/biocutils/subset.py +++ b/src/biocutils/subset.py @@ -1,4 +1,5 @@ -from typing import Any, Sequence +from collections.abc import Sequence +from typing import Any from .is_high_dimensional import is_high_dimensional from .subset_rows import subset_rows diff --git a/src/biocutils/subset_rows.py b/src/biocutils/subset_rows.py index e5b31cb..0fde0ef 100644 --- a/src/biocutils/subset_rows.py +++ b/src/biocutils/subset_rows.py @@ -1,5 +1,6 @@ +from collections.abc import Sequence from functools import singledispatch -from typing import Any, Sequence +from typing import Any import numpy diff --git a/src/biocutils/subset_sequence.py b/src/biocutils/subset_sequence.py index 1c39517..d7e0c3e 100644 --- a/src/biocutils/subset_sequence.py +++ b/src/biocutils/subset_sequence.py @@ -1,5 +1,6 @@ +from collections.abc import Sequence from functools import singledispatch -from typing import Any, Sequence, Union +from typing import Any @singledispatch @@ -36,7 +37,7 @@ def _subset_sequence_list(x: list, indices: Sequence[int]) -> list: @subset_sequence.register -def _subset_sequence_range(x: range, indices: Sequence[int]) -> Union[list, range]: +def _subset_sequence_range(x: range, indices: Sequence[int]) -> list | range: """Subset a range by indices. Args: diff --git a/src/biocutils/table.py b/src/biocutils/table.py index 72d06f5..8b175da 100644 --- a/src/biocutils/table.py +++ b/src/biocutils/table.py @@ -1,5 +1,5 @@ +from collections.abc import Sequence from functools import singledispatch -from typing import Sequence from .IntegerList import IntegerList diff --git a/src/biocutils/union.py b/src/biocutils/union.py index 78e3949..1ca5628 100644 --- a/src/biocutils/union.py +++ b/src/biocutils/union.py @@ -1,4 +1,4 @@ -from typing import Sequence +from collections.abc import Sequence from .is_missing_scalar import is_missing_scalar from .map_to_index import DUPLICATE_METHOD diff --git a/src/biocutils/which.py b/src/biocutils/which.py index ca7a863..9008e72 100644 --- a/src/biocutils/which.py +++ b/src/biocutils/which.py @@ -1,11 +1,11 @@ -from typing import Optional, Sequence +from collections.abc import Sequence import numpy def which( x: Sequence, - dtype: Optional[numpy.dtype] = None, + dtype: numpy.dtype | None = None, ) -> numpy.ndarray: """Report the indices of all elements of ``x`` that are truthy.