Skip to content

Commit

Permalink
Merge pull request #2 from napari/minor-fixes
Browse files Browse the repository at this point in the history
Remove dictionary sample key and branch triggers for release workflow
  • Loading branch information
DragaDoncila authored Nov 3, 2023
2 parents 6d26ef0 + dfa15a1 commit fa07c1f
Show file tree
Hide file tree
Showing 7 changed files with 384 additions and 0 deletions.
28 changes: 28 additions & 0 deletions .github/workflows/release.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
name: release

on:
push:
tags:
- "v*" # Push events to matching v*, i.e. v1.0, v20.15.10
workflow_dispatch:

jobs:
release:
runs-on: ubuntu-latest
permissions:
id-token: write
steps:
- uses: actions/checkout@v3
- name: Set up Python
uses: actions/setup-python@v4
with:
python-version: "3.x"
- name: Install dependencies
run: |
python -m pip install --upgrade pip
pip install -U setuptools setuptools_scm wheel build
- name: build
run: |
python -m build .
- name: Publish
uses: pypa/gh-action-pypi-publish@release/v1
64 changes: 64 additions & 0 deletions .github/workflows/test_pr.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,64 @@
name: tests

on:
push:
branches:
- npe1
- main
tags:
- "v*" # Push events to matching v*, i.e. v1.0, v20.15.10
pull_request:
branches:
- npe1
- main
workflow_dispatch:

jobs:
test:
name: ${{ matrix.platform }} py${{ matrix.python-version }}
runs-on: ${{ matrix.platform }}
strategy:
matrix:
platform: [ubuntu-latest, windows-latest, macos-latest]
python-version: ["3.8", "3.9", "3.10"]

steps:
- uses: actions/checkout@v3
with:
fetch-depth: 0

- name: Set up Python ${{ matrix.python-version }}
uses: actions/setup-python@v4
with:
python-version: ${{ matrix.python-version }}

# these libraries, along with pytest-xvfb (added in the `deps` in tox.ini),
# enable testing on Qt on linux
- uses: tlambert03/setup-qt-libs@v1

# strategy borrowed from vispy for installing opengl libs on windows
- name: Install Windows OpenGL
if: runner.os == 'Windows'
uses: actions/checkout@v3
with:
path: gl-ci-helpers
repository: pyvista/gl-ci-helpers
fetch-depth: 1
- name: Install Windows OpenGL
if: runner.os == 'Windows'
run: |
powershell gl-ci-helpers/appveyor/install_opengl.ps1
# note: if you need dependencies from conda, considering using
# setup-miniconda: https://github.com/conda-incubator/setup-miniconda
# and
# tox-conda: https://github.com/tox-dev/tox-conda
- name: Install dependencies
run: |
python -m pip install --upgrade pip
pip install setuptools pytest pyqt5
pip install .
- name: Test
uses: aganders3/headless-gui@v1
with:
run: python -m pytest -s -v --color=yes
105 changes: 105 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,105 @@
# Byte-compiled / optimized / DLL files
__pycache__/
*.py[cod]
*$py.class

# Distribution / packaging
.Python
build/
develop-eggs/
dist/
downloads/
eggs/
.eggs/
lib/
lib64/
parts/
sdist/
var/
wheels/
*.egg-info/
.installed.cfg
*.egg
MANIFEST
.dmypy.json

# PyInstaller
# Usually these files are written by a python script from a template
# before PyInstaller builds the exe, so as to inject date/other infos into it.
*.manifest
*.spec

# Installer logs
pip-log.txt
pip-delete-this-directory.txt
pip-wheel-metadata/

# Unit test / coverage reports
htmlcov/
.tox/
.coverage
.coverage.*
.cache
nosetests.xml
coverage.xml
*.cover
.hypothesis/
.pytest_cache/

# PyBuilder
target/

# Jupyter Notebook
.ipynb_checkpoints

# pyenv
.python-version

# Environments
.env
.venv
env/
venv/
ENV/
env.bak/
venv.bak/

# Spyder project settings
.spyderproject
.spyproject

# mypy
.mypy_cache/

# Pycharm files
.idea

# Liclipse
.project
.pydevproject
.settings/

# OS stuff
.DS_store

# Benchmarking results
.asv/

# VSCode
.vscode/

# emacs
*~
\#*\#
auto-save-list
tramp
.\#*
*_flymake.*
.projectile
.dir-locals.el

github_cache.sqlite

# version

dummy_test_plugin/_version.py
106 changes: 106 additions & 0 deletions dummy_test_plugin/__init__.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,106 @@
from typing import Dict, List
import numpy as np
from napari_plugin_engine import napari_hook_implementation
from magicgui import magic_factory

#### READER ####
@napari_hook_implementation
def napari_get_reader(path: str):
if not path.endswith(".npy"):
return None
return reader_function


#### SAMPLE ####
@napari_hook_implementation
def napari_provide_sample_data():
return {
'random data': generate_random_data,
'random image': 'https://picsum.photos/1024',
}


#### WRITERS ####
@napari_hook_implementation
def napari_get_writer(path: str, layer_types: List[str]):
if not path.endswith('.npy'):
return None

return save_numpy


@napari_hook_implementation
def napari_write_image(path:str, data: np.ndarray, meta: Dict):
if not path.endswith('.npy'):
return None

saved_path = save_numpy(path, [(data, meta, 'image')])
return saved_path


### WIDGETS ###
@napari_hook_implementation
def napari_experimental_provide_function():
return my_function


@napari_hook_implementation
def napari_experimental_provide_dock_widget():
return threshold


### THEME ###
@napari_hook_implementation
def napari_experimental_provide_theme():
return get_new_theme()


### HELPERS ###
def reader_function(path: str):
data = np.load(path)
return [(data, {}, 'image')]


def generate_random_data(shape=(512, 512)):
data = np.random.rand(*shape)
return [(data, {'name': 'random data'})]


def save_numpy(path, layer_tuples):
data, _, _ = layer_tuples[0]
np.save(path, data)
return path


def my_function(image : 'napari.types.ImageData') -> 'napari.types.LayerDataTuple':
result = -image
return (result, {'colormap':'turbo'}, 'image')


@magic_factory(auto_call=True, threshold={'max': 2 ** 16})
def threshold(
data: 'napari.types.ImageData', threshold: int
) -> 'napari.types.LabelsData':
return (data > threshold).astype(int)


def get_new_theme():
themes = {
"super_dark": {
"name": "super_dark",
"background": "rgb(12, 12, 12)",
"foreground": "rgb(65, 72, 81)",
"primary": "rgb(90, 98, 108)",
"secondary": "rgb(134, 142, 147)",
"highlight": "rgb(106, 115, 128)",
"text": "rgb(240, 241, 242)",
"icon": "rgb(209, 210, 212)",
"warning": "rgb(153, 18, 31)",
"current": "rgb(0, 122, 204)",
"syntax_style": "native",
"console": "rgb(0, 0, 0)",
"canvas": "black",
}
}
return themes

6 changes: 6 additions & 0 deletions pyproject.toml
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
[build-system]
requires = ["setuptools", "wheel", "setuptools_scm"]
build-backend = "setuptools.build_meta"

[tool.setuptools_scm]
write_to = "dummy_test_plugin/_version.py"
22 changes: 22 additions & 0 deletions setup.cfg
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
[metadata]
name = dummy-test-plugin
version = 0.0.1
author = napari team
description = A simple plugin for testing purposes
long_description = file: README.md
long_description_content_type = text/markdown
license = BSD-3-Clause
license_files = LICENSE

[options]
packages = find:
install_requires =
magicgui
napari
napari-plugin-engine>=0.1.4
numpy
qtpy

[options.entry_points]
napari.plugin =
dummy-test-plugin = dummy_test_plugin
53 changes: 53 additions & 0 deletions tests/test_hook_impls.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,53 @@
import numpy as np

from dummy_test_plugin import (
napari_get_reader,
napari_get_writer,
my_function,
threshold
)


def test_reader(tmp_path):
np_path = tmp_path / "test_file.npy"
data = np.ones(shape=(10, 10))
np.save(np_path, data)

reader = napari_get_reader(str(np_path))
assert callable(reader)
read_tuples = reader(np_path)
assert len(read_tuples) == 1
read_tuple = read_tuples[0]
np.testing.assert_allclose(data, read_tuple[0])

fake_path = tmp_path / "file.fake"
reader = napari_get_reader(str(fake_path))
assert reader is None

def test_get_writer(tmp_path):
np_path = tmp_path / "test_file.npy"
data = np.ones(shape=(10, 10))
layer_tuple = (data, {}, 'image')
writer = napari_get_writer(str(np_path), ['image'])
assert callable(writer)
saved_path = writer(np_path, [layer_tuple])
assert saved_path == np_path
loaded_data = np.load(saved_path)
np.testing.assert_allclose(data, loaded_data)

fake_path = tmp_path / "file.fake"
writer = napari_get_writer(str(fake_path), ['image'])
assert writer is None

def test_my_function():
im_data = np.ones(shape=(10, 10), dtype=np.uint8)
func_result = my_function(im_data)
assert len(func_result) == 3
data = func_result[0]
assert np.all(data == 255)

def test_threshold():
widget = threshold()
im_data = np.ones(shape=(10, 10), dtype=np.uint8)
thresholded_im = widget(im_data, 0)
assert np.all(thresholded_im)

0 comments on commit fa07c1f

Please sign in to comment.