biocutils 0.3.0__tar.gz → 0.3.1.dev0__tar.gz

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (113) hide show
  1. biocutils-0.3.1.dev0/.github/workflows/publish-pypi.yml +52 -0
  2. biocutils-0.3.1.dev0/.github/workflows/run-tests.yml +73 -0
  3. {biocutils-0.3.0 → biocutils-0.3.1.dev0}/PKG-INFO +1 -1
  4. {biocutils-0.3.0 → biocutils-0.3.1.dev0}/src/biocutils/__init__.py +9 -7
  5. {biocutils-0.3.0 → biocutils-0.3.1.dev0}/src/biocutils/_utils_combine.py +2 -0
  6. {biocutils-0.3.0 → biocutils-0.3.1.dev0}/src/biocutils/assign.py +2 -1
  7. {biocutils-0.3.0 → biocutils-0.3.1.dev0}/src/biocutils/assign_rows.py +3 -3
  8. {biocutils-0.3.0 → biocutils-0.3.1.dev0}/src/biocutils/assign_sequence.py +2 -6
  9. {biocutils-0.3.0 → biocutils-0.3.1.dev0}/src/biocutils/bioc_object.py +6 -11
  10. biocutils-0.3.0/src/biocutils/BooleanList.py → biocutils-0.3.1.dev0/src/biocutils/boolean_list.py +39 -27
  11. {biocutils-0.3.0 → biocutils-0.3.1.dev0}/src/biocutils/combine.py +5 -5
  12. {biocutils-0.3.0 → biocutils-0.3.1.dev0}/src/biocutils/combine_columns.py +9 -8
  13. {biocutils-0.3.0 → biocutils-0.3.1.dev0}/src/biocutils/combine_rows.py +5 -7
  14. {biocutils-0.3.0 → biocutils-0.3.1.dev0}/src/biocutils/combine_sequences.py +5 -6
  15. {biocutils-0.3.0 → biocutils-0.3.1.dev0}/src/biocutils/convert_to_dense.py +2 -1
  16. {biocutils-0.3.0 → biocutils-0.3.1.dev0}/src/biocutils/extract_column_names.py +4 -3
  17. {biocutils-0.3.0 → biocutils-0.3.1.dev0}/src/biocutils/extract_row_names.py +3 -3
  18. biocutils-0.3.0/src/biocutils/Factor.py → biocutils-0.3.1.dev0/src/biocutils/factor.py +44 -81
  19. biocutils-0.3.0/src/biocutils/FloatList.py → biocutils-0.3.1.dev0/src/biocutils/float_list.py +29 -19
  20. biocutils-0.3.0/src/biocutils/IntegerList.py → biocutils-0.3.1.dev0/src/biocutils/integer_list.py +30 -19
  21. {biocutils-0.3.0 → biocutils-0.3.1.dev0}/src/biocutils/is_high_dimensional.py +4 -2
  22. {biocutils-0.3.0 → biocutils-0.3.1.dev0}/src/biocutils/is_list_of_type.py +7 -4
  23. {biocutils-0.3.0 → biocutils-0.3.1.dev0}/src/biocutils/is_missing_scalar.py +5 -2
  24. {biocutils-0.3.0 → biocutils-0.3.1.dev0}/src/biocutils/map_to_index.py +2 -3
  25. {biocutils-0.3.0 → biocutils-0.3.1.dev0}/src/biocutils/match.py +5 -4
  26. biocutils-0.3.0/src/biocutils/NamedList.py → biocutils-0.3.1.dev0/src/biocutils/named_list.py +36 -46
  27. biocutils-0.3.0/src/biocutils/Names.py → biocutils-0.3.1.dev0/src/biocutils/names.py +25 -20
  28. {biocutils-0.3.0 → biocutils-0.3.1.dev0}/src/biocutils/normalize_subscript.py +18 -26
  29. {biocutils-0.3.0 → biocutils-0.3.1.dev0}/src/biocutils/package_utils.py +4 -3
  30. {biocutils-0.3.0 → biocutils-0.3.1.dev0}/src/biocutils/print_truncated.py +6 -13
  31. {biocutils-0.3.0 → biocutils-0.3.1.dev0}/src/biocutils/print_wrapped_table.py +9 -8
  32. {biocutils-0.3.0 → biocutils-0.3.1.dev0}/src/biocutils/relaxed_combine_columns.py +1 -5
  33. {biocutils-0.3.0 → biocutils-0.3.1.dev0}/src/biocutils/relaxed_combine_rows.py +1 -3
  34. {biocutils-0.3.0 → biocutils-0.3.1.dev0}/src/biocutils/reverse_index.py +5 -4
  35. {biocutils-0.3.0 → biocutils-0.3.1.dev0}/src/biocutils/show_as_cell.py +1 -1
  36. biocutils-0.3.0/src/biocutils/StringList.py → biocutils-0.3.1.dev0/src/biocutils/string_list.py +28 -19
  37. biocutils-0.3.1.dev0/src/biocutils/subset_rows.py +59 -0
  38. biocutils-0.3.1.dev0/src/biocutils/subset_sequence.py +68 -0
  39. biocutils-0.3.1.dev0/src/biocutils/table.py +38 -0
  40. {biocutils-0.3.0 → biocutils-0.3.1.dev0}/src/biocutils/which.py +2 -1
  41. {biocutils-0.3.0 → biocutils-0.3.1.dev0}/src/biocutils.egg-info/PKG-INFO +1 -1
  42. {biocutils-0.3.0 → biocutils-0.3.1.dev0}/src/biocutils.egg-info/SOURCES.txt +10 -9
  43. {biocutils-0.3.0 → biocutils-0.3.1.dev0}/tests/test_biocobject.py +1 -1
  44. biocutils-0.3.0/.github/workflows/pypi-publish.yml +0 -51
  45. biocutils-0.3.0/.github/workflows/pypi-test.yml +0 -40
  46. biocutils-0.3.0/src/biocutils/subset_rows.py +0 -24
  47. biocutils-0.3.0/src/biocutils/subset_sequence.py +0 -42
  48. {biocutils-0.3.0 → biocutils-0.3.1.dev0}/.coveragerc +0 -0
  49. {biocutils-0.3.0 → biocutils-0.3.1.dev0}/.gitignore +0 -0
  50. {biocutils-0.3.0 → biocutils-0.3.1.dev0}/.pre-commit-config.yaml +0 -0
  51. {biocutils-0.3.0 → biocutils-0.3.1.dev0}/.readthedocs.yml +0 -0
  52. {biocutils-0.3.0 → biocutils-0.3.1.dev0}/AUTHORS.md +0 -0
  53. {biocutils-0.3.0 → biocutils-0.3.1.dev0}/CHANGELOG.md +0 -0
  54. {biocutils-0.3.0 → biocutils-0.3.1.dev0}/CONTRIBUTING.md +0 -0
  55. {biocutils-0.3.0 → biocutils-0.3.1.dev0}/LICENSE.txt +0 -0
  56. {biocutils-0.3.0 → biocutils-0.3.1.dev0}/README.md +0 -0
  57. {biocutils-0.3.0 → biocutils-0.3.1.dev0}/docs/Makefile +0 -0
  58. {biocutils-0.3.0 → biocutils-0.3.1.dev0}/docs/_static/.gitignore +0 -0
  59. {biocutils-0.3.0 → biocutils-0.3.1.dev0}/docs/authors.md +0 -0
  60. {biocutils-0.3.0 → biocutils-0.3.1.dev0}/docs/changelog.md +0 -0
  61. {biocutils-0.3.0 → biocutils-0.3.1.dev0}/docs/conf.py +0 -0
  62. {biocutils-0.3.0 → biocutils-0.3.1.dev0}/docs/contributing.md +0 -0
  63. {biocutils-0.3.0 → biocutils-0.3.1.dev0}/docs/index.md +0 -0
  64. {biocutils-0.3.0 → biocutils-0.3.1.dev0}/docs/license.md +0 -0
  65. {biocutils-0.3.0 → biocutils-0.3.1.dev0}/docs/readme.md +0 -0
  66. {biocutils-0.3.0 → biocutils-0.3.1.dev0}/docs/requirements.txt +0 -0
  67. {biocutils-0.3.0 → biocutils-0.3.1.dev0}/pyproject.toml +0 -0
  68. {biocutils-0.3.0 → biocutils-0.3.1.dev0}/setup.cfg +0 -0
  69. {biocutils-0.3.0 → biocutils-0.3.1.dev0}/setup.py +0 -0
  70. {biocutils-0.3.0 → biocutils-0.3.1.dev0}/src/biocutils/factorize.py +0 -0
  71. {biocutils-0.3.0 → biocutils-0.3.1.dev0}/src/biocutils/get_height.py +0 -0
  72. {biocutils-0.3.0 → biocutils-0.3.1.dev0}/src/biocutils/intersect.py +0 -0
  73. {biocutils-0.3.0 → biocutils-0.3.1.dev0}/src/biocutils/subset.py +0 -0
  74. {biocutils-0.3.0 → biocutils-0.3.1.dev0}/src/biocutils/union.py +0 -0
  75. {biocutils-0.3.0 → biocutils-0.3.1.dev0}/src/biocutils.egg-info/dependency_links.txt +0 -0
  76. {biocutils-0.3.0 → biocutils-0.3.1.dev0}/src/biocutils.egg-info/not-zip-safe +0 -0
  77. {biocutils-0.3.0 → biocutils-0.3.1.dev0}/src/biocutils.egg-info/requires.txt +0 -0
  78. {biocutils-0.3.0 → biocutils-0.3.1.dev0}/src/biocutils.egg-info/top_level.txt +0 -0
  79. {biocutils-0.3.0 → biocutils-0.3.1.dev0}/tests/conftest.py +0 -0
  80. {biocutils-0.3.0 → biocutils-0.3.1.dev0}/tests/test_BooleanList.py +0 -0
  81. {biocutils-0.3.0 → biocutils-0.3.1.dev0}/tests/test_Factor.py +0 -0
  82. {biocutils-0.3.0 → biocutils-0.3.1.dev0}/tests/test_FloatList.py +0 -0
  83. {biocutils-0.3.0 → biocutils-0.3.1.dev0}/tests/test_IntegerList.py +0 -0
  84. {biocutils-0.3.0 → biocutils-0.3.1.dev0}/tests/test_NamedList.py +0 -0
  85. {biocutils-0.3.0 → biocutils-0.3.1.dev0}/tests/test_Names.py +0 -0
  86. {biocutils-0.3.0 → biocutils-0.3.1.dev0}/tests/test_StringList.py +0 -0
  87. {biocutils-0.3.0 → biocutils-0.3.1.dev0}/tests/test_assign.py +0 -0
  88. {biocutils-0.3.0 → biocutils-0.3.1.dev0}/tests/test_assign_rows.py +0 -0
  89. {biocutils-0.3.0 → biocutils-0.3.1.dev0}/tests/test_assign_sequence.py +0 -0
  90. {biocutils-0.3.0 → biocutils-0.3.1.dev0}/tests/test_combine.py +0 -0
  91. {biocutils-0.3.0 → biocutils-0.3.1.dev0}/tests/test_combine_columns.py +0 -0
  92. {biocutils-0.3.0 → biocutils-0.3.1.dev0}/tests/test_combine_rows.py +0 -0
  93. {biocutils-0.3.0 → biocutils-0.3.1.dev0}/tests/test_combine_sequences.py +0 -0
  94. {biocutils-0.3.0 → biocutils-0.3.1.dev0}/tests/test_extract_column_names.py +0 -0
  95. {biocutils-0.3.0 → biocutils-0.3.1.dev0}/tests/test_extract_row_names.py +0 -0
  96. {biocutils-0.3.0 → biocutils-0.3.1.dev0}/tests/test_factorize.py +0 -0
  97. {biocutils-0.3.0 → biocutils-0.3.1.dev0}/tests/test_get_height.py +0 -0
  98. {biocutils-0.3.0 → biocutils-0.3.1.dev0}/tests/test_intersect.py +0 -0
  99. {biocutils-0.3.0 → biocutils-0.3.1.dev0}/tests/test_is_high_dimensional.py +0 -0
  100. {biocutils-0.3.0 → biocutils-0.3.1.dev0}/tests/test_list_type_checks.py +0 -0
  101. {biocutils-0.3.0 → biocutils-0.3.1.dev0}/tests/test_map_to_index.py +0 -0
  102. {biocutils-0.3.0 → biocutils-0.3.1.dev0}/tests/test_match.py +0 -0
  103. {biocutils-0.3.0 → biocutils-0.3.1.dev0}/tests/test_normalize_subscript.py +0 -0
  104. {biocutils-0.3.0 → biocutils-0.3.1.dev0}/tests/test_package_utils.py +0 -0
  105. {biocutils-0.3.0 → biocutils-0.3.1.dev0}/tests/test_print_truncated.py +0 -0
  106. {biocutils-0.3.0 → biocutils-0.3.1.dev0}/tests/test_print_wrapped_table.py +0 -0
  107. {biocutils-0.3.0 → biocutils-0.3.1.dev0}/tests/test_show_as_cell.py +0 -0
  108. {biocutils-0.3.0 → biocutils-0.3.1.dev0}/tests/test_subset.py +0 -0
  109. {biocutils-0.3.0 → biocutils-0.3.1.dev0}/tests/test_subset_rows.py +0 -0
  110. {biocutils-0.3.0 → biocutils-0.3.1.dev0}/tests/test_subset_sequence.py +0 -0
  111. {biocutils-0.3.0 → biocutils-0.3.1.dev0}/tests/test_union.py +0 -0
  112. {biocutils-0.3.0 → biocutils-0.3.1.dev0}/tests/test_which.py +0 -0
  113. {biocutils-0.3.0 → biocutils-0.3.1.dev0}/tox.ini +0 -0
@@ -0,0 +1,52 @@
1
+ name: Publish to PyPI
2
+
3
+ on:
4
+ push:
5
+ tags: "*"
6
+
7
+ jobs:
8
+ build:
9
+ runs-on: ubuntu-latest
10
+ permissions:
11
+ id-token: write
12
+ repository-projects: write
13
+ contents: write
14
+ pages: write
15
+
16
+ steps:
17
+ - uses: actions/checkout@v4
18
+
19
+ - name: Set up Python 3.12
20
+ uses: actions/setup-python@v5
21
+ with:
22
+ python-version: 3.12
23
+
24
+ - name: Install dependencies
25
+ run: |
26
+ python -m pip install --upgrade pip
27
+ pip install tox
28
+
29
+ - name: Test with tox
30
+ run: |
31
+ tox
32
+
33
+ - name: Build Project and Publish
34
+ run: |
35
+ python -m tox -e clean,build
36
+
37
+ # This uses the trusted publisher workflow so no token is required.
38
+ - name: Publish to PyPI
39
+ uses: pypa/gh-action-pypi-publish@release/v1
40
+
41
+ - name: Build docs
42
+ run: |
43
+ tox -e docs
44
+
45
+ - run: touch ./docs/_build/html/.nojekyll
46
+
47
+ - name: GH Pages Deployment
48
+ uses: JamesIves/github-pages-deploy-action@v4
49
+ with:
50
+ branch: gh-pages # The branch the action should deploy to.
51
+ folder: ./docs/_build/html
52
+ clean: true # Automatically remove deleted files from the deploy branch
@@ -0,0 +1,73 @@
1
+ name: Test the library
2
+
3
+ on:
4
+ push:
5
+ branches:
6
+ - master # for legacy repos
7
+ - main
8
+ pull_request:
9
+ branches:
10
+ - master # for legacy repos
11
+ - main
12
+ workflow_dispatch: # Allow manually triggering the workflow
13
+ schedule:
14
+ # Run roughly every 15 days at 00:00 UTC
15
+ # (useful to check if updates on dependencies break the package)
16
+ - cron: "0 0 1,16 * *"
17
+
18
+ permissions:
19
+ contents: read
20
+
21
+ concurrency:
22
+ group: >-
23
+ ${{ github.workflow }}-${{ github.ref_type }}-
24
+ ${{ github.event.pull_request.number || github.sha }}
25
+ cancel-in-progress: true
26
+
27
+ jobs:
28
+ test:
29
+ strategy:
30
+ matrix:
31
+ python: ["3.10", "3.11", "3.12", "3.13", "3.14"]
32
+ platform:
33
+ - ubuntu-latest
34
+ - macos-latest
35
+ - windows-latest
36
+ runs-on: ${{ matrix.platform }}
37
+ name: Python ${{ matrix.python }}, ${{ matrix.platform }}
38
+ steps:
39
+ - uses: actions/checkout@v4
40
+
41
+ - uses: actions/setup-python@v5
42
+ id: setup-python
43
+ with:
44
+ python-version: ${{ matrix.python }}
45
+
46
+ - name: Install dependencies
47
+ run: |
48
+ python -m pip install --upgrade pip
49
+ pip install tox coverage
50
+
51
+ - name: Run tests
52
+ run: >-
53
+ pipx run --python '${{ steps.setup-python.outputs.python-path }}'
54
+ tox
55
+ -- -rFEx --durations 10 --color yes --cov --cov-branch --cov-report=xml # pytest args
56
+
57
+ - name: Check for codecov token availability
58
+ id: codecov-check
59
+ shell: bash
60
+ run: |
61
+ if [ ${{ secrets.CODECOV_TOKEN }} != '' ]; then
62
+ echo "codecov=true" >> $GITHUB_OUTPUT;
63
+ else
64
+ echo "codecov=false" >> $GITHUB_OUTPUT;
65
+ fi
66
+
67
+ - name: Upload coverage reports to Codecov with GitHub Action
68
+ uses: codecov/codecov-action@v5
69
+ if: ${{ steps.codecov-check.outputs.codecov == 'true' }}
70
+ env:
71
+ CODECOV_TOKEN: ${{ secrets.CODECOV_TOKEN }}
72
+ slug: ${{ github.repository }}
73
+ flags: ${{ matrix.platform }} - py${{ matrix.python }}
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: biocutils
3
- Version: 0.3.0
3
+ Version: 0.3.1.dev0
4
4
  Summary: Utilities to use across the biocpy packages.
5
5
  Home-page: https://github.com/biocpy/biocutils
6
6
  Author: Aaron Lun
@@ -15,13 +15,13 @@ except PackageNotFoundError: # pragma: no cover
15
15
  finally:
16
16
  del version, PackageNotFoundError
17
17
 
18
- from .Factor import Factor
19
- from .StringList import StringList
20
- from .IntegerList import IntegerList
21
- from .FloatList import FloatList
22
- from .BooleanList import BooleanList
23
- from .Names import Names
24
- from .NamedList import NamedList
18
+ from .factor import Factor
19
+ from .string_list import StringList
20
+ from .integer_list import IntegerList
21
+ from .float_list import FloatList
22
+ from .boolean_list import BooleanList
23
+ from .names import Names
24
+ from .named_list import NamedList
25
25
 
26
26
  from .factorize import factorize
27
27
  from .intersect import intersect
@@ -60,3 +60,5 @@ from .convert_to_dense import convert_to_dense
60
60
 
61
61
  from .get_height import get_height
62
62
  from .is_high_dimensional import is_high_dimensional
63
+
64
+ from .bioc_object import BiocObject
@@ -26,6 +26,8 @@ def _check_array_dimensions(x, active: int) -> bool:
26
26
  + ")"
27
27
  )
28
28
 
29
+ return True
30
+
29
31
 
30
32
  def _coerce_sparse_matrix(first, combined, module):
31
33
  if isinstance(first, module.csr_matrix):
@@ -14,7 +14,8 @@ def assign(x: Any, indices: Sequence[int], replacement: Any) -> Any:
14
14
  :py:func:`~biocutils.assign_sequence.assign_sequence` instead.
15
15
 
16
16
  Args:
17
- x: Object to be assignted.
17
+ x:
18
+ Object to be assignted.
18
19
 
19
20
  Returns:
20
21
  The object after assignment, typically the same type as ``x``.
@@ -31,15 +31,15 @@ def assign_rows(x: Any, indices: Sequence[int], replacement: Any) -> Any:
31
31
  tmp = [slice(None)] * len(x.shape)
32
32
  tmp[0] = indices
33
33
  output[(*tmp,)] = replacement
34
+
34
35
  return output
35
36
 
36
37
 
37
38
  @assign_rows.register
38
- def _assign_rows_numpy(
39
- x: numpy.ndarray, indices: Sequence[int], replacement: Any
40
- ) -> numpy.ndarray:
39
+ def _assign_rows_numpy(x: numpy.ndarray, indices: Sequence[int], replacement: Any) -> numpy.ndarray:
41
40
  tmp = [slice(None)] * len(x.shape)
42
41
  tmp[0] = indices
43
42
  output = numpy.copy(x)
44
43
  output[(*tmp,)] = replacement
44
+
45
45
  return output
@@ -41,18 +41,14 @@ def _assign_sequence_list(x: list, indices: Sequence[int], replacement: Any) ->
41
41
 
42
42
 
43
43
  @assign_sequence.register
44
- def _assign_sequence_numpy(
45
- x: numpy.ndarray, indices: Sequence[int], replacement: Any
46
- ) -> numpy.ndarray:
44
+ def _assign_sequence_numpy(x: numpy.ndarray, indices: Sequence[int], replacement: Any) -> numpy.ndarray:
47
45
  output = numpy.copy(x)
48
46
  output[indices] = replacement
49
47
  return output
50
48
 
51
49
 
52
50
  @assign_sequence.register
53
- def _assign_sequence_range(
54
- x: range, indices: Sequence[int], replacement: Any
55
- ) -> Union[range, list]:
51
+ def _assign_sequence_range(x: range, indices: Sequence[int], replacement: Any) -> Union[range, list]:
56
52
  if (
57
53
  isinstance(replacement, range)
58
54
  and isinstance(indices, range)
@@ -4,12 +4,7 @@ import copy
4
4
  from typing import Any, Dict, Optional, Union
5
5
  from warnings import warn
6
6
 
7
- try:
8
- from typing import Self
9
- except ImportError:
10
- Self = "BiocObject"
11
-
12
- from .NamedList import NamedList
7
+ from .named_list import NamedList
13
8
 
14
9
  __author__ = "Jayaram Kancherla"
15
10
  __copyright__ = "jkanche"
@@ -40,22 +35,22 @@ class BiocObject:
40
35
  Provides a standardized `metadata` slot and copy-on-write semantics.
41
36
  """
42
37
 
43
- def __init__(self, metadata: Optional[Union[Dict[str, Any], NamedList]] = None, validate: bool = True) -> None:
38
+ def __init__(self, metadata: Optional[Union[Dict[str, Any], NamedList]] = None, _validate: bool = True) -> None:
44
39
  """Initialize the BiocObject.
45
40
 
46
41
  Args:
47
42
  metadata:
48
43
  Additional metadata. Defaults to an empty NamedList.
49
44
 
50
- validate:
45
+ _validate:
51
46
  Whether to validate the input. Defaults to True.
52
47
  """
53
- if validate and metadata is not None:
48
+ if _validate and metadata is not None:
54
49
  _validate_metadata(metadata)
55
50
 
56
51
  self._metadata = sanitize_metadata(metadata)
57
52
 
58
- def _define_output(self, in_place: bool = False) -> Self:
53
+ def _define_output(self, in_place: bool = False) -> BiocObject:
59
54
  """Internal utility to handle in-place vs copy-on-modify."""
60
55
  if in_place:
61
56
  return self
@@ -93,7 +88,7 @@ class BiocObject:
93
88
  """Alias for :py:attr:`~metadata` getter."""
94
89
  return self.metadata
95
90
 
96
- def set_metadata(self, metadata: Optional[Union[Dict[str, Any], NamedList]], in_place: bool = False) -> Self:
91
+ def set_metadata(self, metadata: Optional[Union[Dict[str, Any], NamedList]], in_place: bool = False) -> BiocObject:
97
92
  """Set new metadata.
98
93
 
99
94
  Args:
@@ -1,7 +1,9 @@
1
+ from __future__ import annotations
2
+
1
3
  from typing import Any, Iterable, Optional, Sequence, Union
2
4
 
3
- from .NamedList import NamedList
4
- from .Names import Names
5
+ from .named_list import NamedList
6
+ from .names import Names
5
7
  from .normalize_subscript import SubscriptTypes
6
8
 
7
9
 
@@ -10,10 +12,27 @@ def _coerce_to_bool(x: Any):
10
12
 
11
13
 
12
14
  class _SubscriptCoercer:
13
- def __init__(self, data):
15
+ """Coercer for subscript operations on BooleanList."""
16
+
17
+ def __init__(self, data: Sequence) -> None:
18
+ """Initialize the coercer.
19
+
20
+ Args:
21
+ data:
22
+ Sequence of values to coerce.
23
+ """
14
24
  self._data = data
15
25
 
16
- def __getitem__(self, index):
26
+ def __getitem__(self, index: int) -> Optional[bool]:
27
+ """Get an item and coerce it to boolean.
28
+
29
+ Args:
30
+ index:
31
+ Index of the item.
32
+
33
+ Returns:
34
+ Coerced boolean value.
35
+ """
17
36
  return _coerce_to_bool(self._data[index])
18
37
 
19
38
 
@@ -27,7 +46,7 @@ class BooleanList(NamedList):
27
46
 
28
47
  def __init__(
29
48
  self,
30
- data: Optional[Iterable] = None,
49
+ data: Optional[Sequence] = None,
31
50
  names: Optional[Names] = None,
32
51
  _validate: bool = True,
33
52
  ):
@@ -45,41 +64,34 @@ class BooleanList(NamedList):
45
64
  _validate:
46
65
  Internal use only.
47
66
  """
48
- if _validate:
49
- if data is not None:
50
- if isinstance(data, BooleanList):
67
+ if data is not None:
68
+ if isinstance(data, BooleanList):
69
+ data = data._data
70
+ else:
71
+ if isinstance(data, NamedList):
51
72
  data = data._data
52
- else:
53
- if isinstance(data, NamedList):
54
- data = data._data
55
- original = data
56
- data = list(_coerce_to_bool(item) for item in original)
73
+
74
+ original = data
75
+ data = list(_coerce_to_bool(item) for item in original)
76
+
57
77
  super().__init__(data, names, _validate=_validate)
58
78
 
59
- def set_value(
60
- self, index: Union[int, str], value: Any, in_place: bool = False
61
- ) -> "BooleanList":
79
+ def set_value(self, index: Union[int, str], value: Any, in_place: bool = False) -> BooleanList:
62
80
  """Calls :py:meth:`~biocutils.NamedList.NamedList.set_value` after coercing ``value`` to a boolean."""
63
81
  return super().set_value(index, _coerce_to_bool(value), in_place=in_place)
64
82
 
65
- def set_slice(
66
- self, index: SubscriptTypes, value: Sequence, in_place: bool = False
67
- ) -> "BooleanList":
83
+ def set_slice(self, index: SubscriptTypes, value: Sequence, in_place: bool = False) -> BooleanList:
68
84
  """Calls :py:meth:`~biocutils.NamedList.NamedList.set_slice` after coercing ``value`` to booleans."""
69
85
  return super().set_slice(index, _SubscriptCoercer(value), in_place=in_place)
70
86
 
71
- def safe_insert(
72
- self, index: Union[int, str], value: Any, in_place: bool = False
73
- ) -> "BooleanList":
87
+ def safe_insert(self, index: Union[int, str], value: Any, in_place: bool = False) -> BooleanList:
74
88
  """Calls :py:meth:`~biocutils.NamedList.NamedList.safe_insert` after coercing ``value`` to a boolean."""
75
89
  return super().safe_insert(index, _coerce_to_bool(value), in_place=in_place)
76
90
 
77
- def safe_append(self, value: Any, in_place: bool = False) -> "BooleanList":
91
+ def safe_append(self, value: Any, in_place: bool = False) -> BooleanList:
78
92
  """Calls :py:meth:`~biocutils.NamedList.NamedList.safe_append` after coercing ``value`` to a boolean."""
79
93
  return super().safe_append(_coerce_to_bool(value), in_place=in_place)
80
94
 
81
- def safe_extend(self, other: Iterable, in_place: bool = True) -> "BooleanList":
95
+ def safe_extend(self, other: Iterable, in_place: bool = False) -> BooleanList:
82
96
  """Calls :py:meth:`~biocutils.NamedList.NamedList.safe_extend` after coercing elements of ``other`` to booleans."""
83
- return super().safe_extend(
84
- (_coerce_to_bool(y) for y in other), in_place=in_place
85
- )
97
+ return super().safe_extend((_coerce_to_bool(y) for y in other), in_place=in_place)
@@ -5,7 +5,7 @@ from .combine_sequences import combine_sequences
5
5
  from .is_high_dimensional import is_high_dimensional
6
6
 
7
7
 
8
- def combine(*x: Any):
8
+ def combine(*x: Any) -> Any:
9
9
  """
10
10
  Generic combine that checks if the objects are n-dimensional for n > 1
11
11
  (i.e. has a ``shape`` property of length greater than 1); if so, it calls
@@ -14,7 +14,8 @@ def combine(*x: Any):
14
14
  :py:func:`~biocutils.combine_sequences.combine_sequences` instead.
15
15
 
16
16
  Args:
17
- x: Objects to combine.
17
+ x:
18
+ Objects to combine.
18
19
 
19
20
  Returns:
20
21
  A combined object, typically the same type as the first element in ``x``.
@@ -28,9 +29,8 @@ def combine(*x: Any):
28
29
  has_1d = True
29
30
 
30
31
  if has_nd and has_1d:
31
- raise ValueError(
32
- "cannot mix 1-dimensional and higher-dimensional objects in `combine`"
33
- )
32
+ raise ValueError("cannot mix 1-dimensional and higher-dimensional objects in `combine`")
33
+
34
34
  if has_nd:
35
35
  return combine_rows(*x)
36
36
  else:
@@ -19,7 +19,7 @@ __license__ = "MIT"
19
19
 
20
20
 
21
21
  @singledispatch
22
- def combine_columns(*x: Any):
22
+ def combine_columns(*x: Any) -> Any:
23
23
  """Combine n-dimensional objects along the second dimension.
24
24
 
25
25
  If all elements are :py:class:`~numpy.ndarray`,
@@ -40,11 +40,7 @@ def combine_columns(*x: Any):
40
40
  Returns:
41
41
  Combined object, typically the same type as the first entry of ``x``
42
42
  """
43
- raise NotImplementedError(
44
- "no `combine_columns` method implemented for '"
45
- + type(x[0]).__name__
46
- + "' objects"
47
- )
43
+ raise NotImplementedError("no `combine_columns` method implemented for '" + type(x[0]).__name__ + "' objects")
48
44
 
49
45
 
50
46
  @combine_columns.register
@@ -57,7 +53,7 @@ def _combine_columns_dense_arrays(*x: numpy.ndarray):
57
53
  return numpy.concatenate(x, axis=1)
58
54
 
59
55
 
60
- if is_package_installed("scipy") is True:
56
+ if is_package_installed("scipy"):
61
57
  import scipy.sparse as sp
62
58
 
63
59
  def _combine_columns_sparse_matrices(*x):
@@ -85,8 +81,13 @@ if is_package_installed("scipy") is True:
85
81
  x = [convert_to_dense(y) for y in x]
86
82
  return numpy.concatenate(x, axis=1)
87
83
 
84
+ try:
85
+ combine_columns.register(sp.sparray, _combine_columns_sparse_arrays)
86
+ except Exception:
87
+ pass
88
+
88
89
 
89
- if is_package_installed("pandas") is True:
90
+ if is_package_installed("pandas"):
90
91
  from pandas import DataFrame, concat
91
92
 
92
93
  @combine_columns.register(DataFrame)
@@ -19,7 +19,7 @@ __license__ = "MIT"
19
19
 
20
20
 
21
21
  @singledispatch
22
- def combine_rows(*x: Any):
22
+ def combine_rows(*x: Any) -> Any:
23
23
  """Combine n-dimensional objects along their first dimension.
24
24
 
25
25
  If all elements are :py:class:`~numpy.ndarray`, we combine them using
@@ -40,9 +40,7 @@ def combine_rows(*x: Any):
40
40
  Returns:
41
41
  Combined object, typically the same type as the first entry of ``x``.
42
42
  """
43
- raise NotImplementedError(
44
- "no `combine_rows` method implemented for '" + type(x[0]).__name__ + "' objects"
45
- )
43
+ raise NotImplementedError("no `combine_rows` method implemented for '" + type(x[0]).__name__ + "' objects")
46
44
 
47
45
 
48
46
  @combine_rows.register(numpy.ndarray)
@@ -69,7 +67,7 @@ if is_package_installed("scipy"):
69
67
  return numpy.concatenate(x)
70
68
 
71
69
  try:
72
- combine_rows.register(sp.sparray, _combine_rows_sparse_arrays)
70
+ combine_rows.register(sp.spmatrix, _combine_rows_sparse_matrices)
73
71
  except Exception:
74
72
  pass
75
73
 
@@ -77,14 +75,14 @@ if is_package_installed("scipy"):
77
75
  _check_array_dimensions(x, 0)
78
76
  if is_list_of_type(x, sp.sparray):
79
77
  combined = sp.vstack(x)
80
- return _coerce_sparse_array(first, combined, sp)
78
+ return _coerce_sparse_array(x[0], combined, sp)
81
79
 
82
80
  warn("not all elements are SciPy sparse arrays")
83
81
  x = [convert_to_dense(y) for y in x]
84
82
  return numpy.concatenate(x)
85
83
 
86
84
  try:
87
- combine_rows.register(sp.spmatrix, _combine_rows_sparse_matrices)
85
+ combine_rows.register(sp.sparray, _combine_rows_sparse_arrays)
88
86
  except Exception:
89
87
  pass
90
88
 
@@ -13,7 +13,7 @@ __license__ = "MIT"
13
13
 
14
14
 
15
15
  @singledispatch
16
- def combine_sequences(*x: Any):
16
+ def combine_sequences(*x: Any) -> Any:
17
17
  """Combine vector-like objects (1-dimensional arrays).
18
18
 
19
19
  If all elements are :py:class:`~numpy.ndarray`,
@@ -34,11 +34,7 @@ def combine_sequences(*x: Any):
34
34
  Returns:
35
35
  A combined object, ideally of the same type as the first element in ``x``.
36
36
  """
37
- raise NotImplementedError(
38
- "no `combine_sequences` method implemented for '"
39
- + type(x[0]).__name__
40
- + "' objects"
41
- )
37
+ raise NotImplementedError("no `combine_sequences` method implemented for '" + type(x[0]).__name__ + "' objects")
42
38
 
43
39
 
44
40
  @combine_sequences.register(list)
@@ -51,6 +47,7 @@ def _combine_sequences_dense_arrays(*x: numpy.ndarray):
51
47
  for y in x:
52
48
  if numpy.ma.is_masked(y):
53
49
  return numpy.ma.concatenate(x, axis=None)
50
+
54
51
  return numpy.concatenate(x, axis=None)
55
52
 
56
53
 
@@ -85,6 +82,7 @@ def _combine_sequences_ranges(*x: range):
85
82
 
86
83
  if not failed:
87
84
  return range(start, stop, step)
85
+
88
86
  return list(chain(*x))
89
87
 
90
88
 
@@ -101,4 +99,5 @@ if is_package_installed("pandas") is True:
101
99
  else:
102
100
  elems.append(elem)
103
101
  x = elems
102
+
104
103
  return concat(x)
@@ -15,7 +15,8 @@ def convert_to_dense(x: Any) -> numpy.ndarray:
15
15
  ``numpy.concatenate`` doesn't understand.
16
16
 
17
17
  Args:
18
- x: Some array-like object to be stored as a NumPy array.
18
+ x:
19
+ Some array-like object to be stored as a NumPy array.
19
20
 
20
21
  Returns:
21
22
  A NumPy array.
@@ -11,11 +11,12 @@ __license__ = "MIT"
11
11
 
12
12
 
13
13
  @singledispatch
14
- def extract_column_names(x: Any) -> numpy.ndarray:
14
+ def extract_column_names(x: Any) -> Any:
15
15
  """Access column names from 2-dimensional representations.
16
16
 
17
17
  Args:
18
- x: Any object.
18
+ x:
19
+ Any object with column names.
19
20
 
20
21
  Returns:
21
22
  Array of strings containing column names.
@@ -27,5 +28,5 @@ if is_package_installed("pandas") is True:
27
28
  from pandas import DataFrame
28
29
 
29
30
  @extract_column_names.register(DataFrame)
30
- def _colnames_dataframe(x: DataFrame) -> list:
31
+ def _colnames_dataframe(x):
31
32
  return numpy.array(x.columns, dtype=str)
@@ -11,11 +11,11 @@ __license__ = "MIT"
11
11
 
12
12
 
13
13
  @singledispatch
14
- def extract_row_names(x: Any) -> numpy.ndarray:
14
+ def extract_row_names(x: Any) -> Any:
15
15
  """Access row names from 2-dimensional representations.
16
16
 
17
17
  Args:
18
- x: Any object.
18
+ x: Any object with row names.
19
19
 
20
20
  Returns:
21
21
  Array of strings containing row names.
@@ -27,5 +27,5 @@ if is_package_installed("pandas") is True:
27
27
  from pandas import DataFrame
28
28
 
29
29
  @extract_row_names.register(DataFrame)
30
- def _rownames_dataframe(x: DataFrame) -> list:
30
+ def _rownames_dataframe(x):
31
31
  return numpy.array(x.index, dtype=str)