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

ci: test windows #29

Open
wants to merge 22 commits into
base: main
Choose a base branch
from
Open
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
51 changes: 43 additions & 8 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -23,17 +23,52 @@ jobs:
- run: pipx run check-manifest

test:
uses: pyapp-kit/workflows/.github/workflows/test-pyrepo.yml@v2
with:
os: ${{ matrix.os }}
python-version: ${{ matrix.python-version }}
coverage-upload: artifact
qt: pyqt6
name: ${{ matrix.platform }} (${{ matrix.python-version }})
runs-on: ${{ matrix.platform }}
strategy:
fail-fast: false
matrix:
os: [ubuntu-latest, macos-latest]
python-version: ["3.8", "3.10", "3.11"]
python-version: ["3.10", "3.11", "3.12"]
platform: [ubuntu-latest, macos-latest, windows-latest]

steps:
- uses: actions/checkout@v4

- uses: pyvista/setup-headless-display-action@v2
with:
qt: true
# strangely, this lib is in headless-display-action, but doesn't get installed
- if: runner.os == 'Linux'
run: sudo apt-get install -y libxcb-cursor0

- uses: actions/setup-python@v4
with:
python-version: ${{ matrix.python-version }}
cache-dependency-path: "pyproject.toml"
cache: "pip"

- name: Install Dependencies
run: |
python -m pip install -U pip
python -m pip install .[test,pyqt]

- name: 🧪 Run Tests
run: coverage run -p -m pytest --color=yes

- name: Generate UUID
shell: bash
run: |
if [[ "$RUNNER_OS" == "Windows" ]]; then
echo "UUID=$(powershell -Command "[guid]::NewGuid().ToString()")" >> $GITHUB_ENV
else
echo "UUID=$(uuidgen)" >> $GITHUB_ENV
fi

- name: Upload coverage data
uses: actions/upload-artifact@v4
with:
name: covreport-${{ matrix.platform }}-py${{ matrix.python-version }}-${{ env.UUID }}
path: ./.coverage*

test-array-libs:
uses: pyapp-kit/workflows/.github/workflows/test-pyrepo.yml@v2
Expand Down
46 changes: 33 additions & 13 deletions src/ndv/viewer/_data_wrapper.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,8 +2,10 @@

from __future__ import annotations

import atexit
import logging
import sys
import threading
from abc import abstractmethod
from concurrent.futures import Future, ThreadPoolExecutor
from contextlib import suppress
Expand Down Expand Up @@ -61,6 +63,11 @@
_EXECUTOR = ThreadPoolExecutor(max_workers=2)


@atexit.register
def _cleanup_executor() -> None:
_EXECUTOR.shutdown(wait=False)

Check warning on line 68 in src/ndv/viewer/_data_wrapper.py

View check run for this annotation

Codecov / codecov/patch

src/ndv/viewer/_data_wrapper.py#L68

Added line #L68 was not covered by tests


def _recurse_subclasses(cls: _T) -> Iterator[_T]:
for subclass in cls.__subclasses__():
yield subclass
Expand Down Expand Up @@ -104,6 +111,7 @@

def __init__(self, data: ArrayT) -> None:
self._data = data
self._lock = threading.Lock()

@property
def data(self) -> ArrayT:
Expand Down Expand Up @@ -197,7 +205,8 @@
"""Wrapper for xarray DataArray objects."""

def isel(self, indexers: Indices) -> np.ndarray:
return np.asarray(self._data.isel(indexers))
with self._lock:
return np.asarray(self._data.isel(indexers))

Check warning on line 209 in src/ndv/viewer/_data_wrapper.py

View check run for this annotation

Codecov / codecov/patch

src/ndv/viewer/_data_wrapper.py#L208-L209

Added lines #L208 - L209 were not covered by tests

def sizes(self) -> Mapping[Hashable, int]:
return {k: int(v) for k, v in self._data.sizes.items()}
Expand Down Expand Up @@ -252,8 +261,9 @@
labels, values = zip(*indexers.items())
origins = (0,) * len(labels)
slc = self._ts.d[labels].translate_to[origins][values]
result = self._data[slc].read().result()
return np.asarray(result)
with self._lock:
result = self._data[slc].read().result()
return np.asarray(result)

Check warning on line 266 in src/ndv/viewer/_data_wrapper.py

View check run for this annotation

Codecov / codecov/patch

src/ndv/viewer/_data_wrapper.py#L264-L266

Added lines #L264 - L266 were not covered by tests

@classmethod
def supports(cls, obj: Any) -> TypeGuard[ts.TensorStore]:
Expand All @@ -268,8 +278,11 @@
PRIORITY = 100

def isel(self, indexers: Indices) -> np.ndarray:
idx = tuple(indexers.get(k, slice(None)) for k in range(len(self._data.shape)))
return self._asarray(self._data[idx])
with self._lock:
idx = tuple(
indexers.get(k, slice(None)) for k in range(len(self._data.shape))
)
return self._asarray(self._data[idx])

def _asarray(self, data: npt.ArrayLike) -> np.ndarray:
return np.asarray(data)
Expand Down Expand Up @@ -305,8 +318,11 @@
"""Wrapper for dask array objects."""

def isel(self, indexers: Indices) -> np.ndarray:
idx = tuple(indexers.get(k, slice(None)) for k in range(len(self._data.shape)))
return np.asarray(self._data[idx].compute())
with self._lock:
idx = tuple(
indexers.get(k, slice(None)) for k in range(len(self._data.shape))
)
return np.asarray(self._data[idx].compute())

@classmethod
def supports(cls, obj: Any) -> TypeGuard[da.Array]:
Expand Down Expand Up @@ -374,8 +390,9 @@

def isel(self, indexers: Indices) -> np.ndarray:
# convert possibly named indices to integer indices
real_indexers = {self._name2index.get(k, k): v for k, v in indexers.items()}
return super().isel(real_indexers)
with self._lock:
real_indexers = {self._name2index.get(k, k): v for k, v in indexers.items()}
return super().isel(real_indexers)

Check warning on line 395 in src/ndv/viewer/_data_wrapper.py

View check run for this annotation

Codecov / codecov/patch

src/ndv/viewer/_data_wrapper.py#L393-L395

Added lines #L393 - L395 were not covered by tests


class TorchTensorWrapper(DataWrapper["torch.Tensor"]):
Expand All @@ -397,10 +414,13 @@

def isel(self, indexers: Indices) -> np.ndarray:
# convert possibly named indices to integer indices
real_indexers = {self._name2index.get(k, k): v for k, v in indexers.items()}
# convert to tuple of slices
idx = tuple(real_indexers.get(i, slice(None)) for i in range(self.data.ndim))
return self.data[idx].numpy(force=True) # type: ignore [no-any-return]
with self._lock:
real_indexers = {self._name2index.get(k, k): v for k, v in indexers.items()}

Check warning on line 418 in src/ndv/viewer/_data_wrapper.py

View check run for this annotation

Codecov / codecov/patch

src/ndv/viewer/_data_wrapper.py#L417-L418

Added lines #L417 - L418 were not covered by tests
# convert to tuple of slices
idx = tuple(

Check warning on line 420 in src/ndv/viewer/_data_wrapper.py

View check run for this annotation

Codecov / codecov/patch

src/ndv/viewer/_data_wrapper.py#L420

Added line #L420 was not covered by tests
real_indexers.get(i, slice(None)) for i in range(self.data.ndim)
)
return self.data[idx].numpy(force=True) # type: ignore [no-any-return]

Check warning on line 423 in src/ndv/viewer/_data_wrapper.py

View check run for this annotation

Codecov / codecov/patch

src/ndv/viewer/_data_wrapper.py#L423

Added line #L423 was not covered by tests

@classmethod
def supports(cls, obj: Any) -> TypeGuard[torch.Tensor]:
Expand Down
Loading