Skip to content

Commit f2e4348

Browse files
authored
ci: Use UV_PYTHON to set python version in tests (#714)
* ci: Use UV_PYTHON to set python version in tests * Use old annotations in test_descriptor.py
1 parent 478e742 commit f2e4348

File tree

5 files changed

+35
-41
lines changed

5 files changed

+35
-41
lines changed

.github/workflows/ci.yml

Lines changed: 5 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -24,7 +24,7 @@ jobs:
2424
sed -i '' 's/\[tool.hatch.build.hooks.\(.*\)\]/\[_tool.hatch.build.hooks.\1\]/' pyproject.toml
2525
- uses: astral-sh/setup-uv@v3
2626
with:
27-
version: "0.4.16"
27+
version: "0.4.x"
2828
- run: |
2929
uv run ruff check
3030
uv run ruff format
@@ -39,7 +39,7 @@ jobs:
3939
sed -i '' 's/\[tool.hatch.build.hooks.\(.*\)\]/\[_tool.hatch.build.hooks.\1\]/' pyproject.toml
4040
- uses: astral-sh/setup-uv@v3
4141
with:
42-
version: "0.4.16"
42+
version: "0.4.x"
4343
- run: uv run mypy
4444

4545
TestPython:
@@ -55,17 +55,16 @@ jobs:
5555
- "3.12"
5656
steps:
5757
- uses: actions/checkout@v4
58-
- uses: actions/setup-python@v5
59-
with:
60-
python-version-file: ".python-version"
6158
- uses: pnpm/action-setup@v4
6259
with:
6360
run_install: true
6461
- uses: astral-sh/setup-uv@v3
6562
with:
66-
version: "0.4.16"
63+
version: "0.4.x"
6764
- name: Run tests
6865
run: uv run --with pytest-cov pytest ./tests --color=yes --cov anywidget --cov-report xml
66+
env:
67+
UV_PYTHON: ${{ matrix.python-version }}
6968
- uses: codecov/codecov-action@v4
7069

7170
LintJavaScript:

.github/workflows/release.yml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -27,7 +27,7 @@ jobs:
2727
run_install: true
2828
- uses: astral-sh/setup-uv@v3
2929
with:
30-
version: "0.4.16"
30+
version: "0.4.x"
3131
- name: Create Release Pull Request or Publish
3232
id: changesets
3333
uses: changesets/action@v1

.python-version

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1 +1 @@
1-
3.11
1+
3.12

pyproject.toml

Lines changed: 15 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -5,14 +5,12 @@ build-backend = "hatchling.build"
55
[project]
66
name = "anywidget"
77
description = "custom jupyter widgets made easy"
8-
authors = [
9-
{ name = "Trevor Manz", email = "[email protected]" }
10-
]
8+
authors = [{ name = "Trevor Manz", email = "[email protected]" }]
119
license = { text = "MIT" }
1210
dynamic = ["version"]
1311
readme = "README.md"
1412
requires-python = ">=3.8"
15-
dependencies = [
13+
dependencies = [
1614
"ipywidgets>=7.6.0",
1715
"typing-extensions>=4.2.0",
1816
"psygnal>=0.8.1",
@@ -69,9 +67,7 @@ skip-if-exists = [
6967
"anywidget/nbextension/index.js",
7068
"anywidget/labextension/package.json",
7169
]
72-
dependencies = [
73-
"hatch-jupyter-builder>=0.5.0",
74-
]
70+
dependencies = ["hatch-jupyter-builder>=0.5.0"]
7571

7672
[tool.hatch.build.hooks.jupyter-builder.build-kwargs]
7773
npm = "pnpm"
@@ -91,20 +87,24 @@ exclude = ["packages", "docs"]
9187
pydocstyle = { convention = "numpy" }
9288
select = ["ALL"]
9389
ignore = [
94-
"D401", # First line should be in imperative mood (remove to opt in)
90+
"D401", # First line should be in imperative mood (remove to opt in)
9591
"COM812", # Missing trailing comma (conflicts with ruff format)
9692
"ISC001", # Import sorting (conflicts with ruff format)
9793
"FIX002", # Fixable issue
9894
"DOC201", # TODO(manzt) enable in follow-up PR; no doc for return type.
99-
"FBT", # TODO(manzt): enable in follow-up PR; require bool options to be keyword-only.
95+
"FBT", # TODO(manzt): enable in follow-up PR; require bool options to be keyword-only.
10096
]
10197

10298
[tool.ruff.lint.per-file-ignores]
10399
"tests/*.py" = [
104-
"D", # No docstrings in tests
105-
"S101", # Use of assert
106-
"B018", # "useless expression", for accessing the Foo._repr_mimbundle_ descriptor
100+
"D", # No docstrings in tests
101+
"S101", # Use of assert
102+
"B018", # "useless expression", for accessing the Foo._repr_mimbundle_ descriptor
107103
"SLF001", # Access private member
104+
"PLC2701" # Private imports
105+
]
106+
"tests/test_descriptor.py" = [
107+
"FA100" # Don't add 'from __future__ import annotations' because it messes with Pydantic and ClassVar
108108
]
109109
"docs/*.py" = ["D"]
110110

@@ -131,7 +131,7 @@ exclude_lines = [
131131
"@overload",
132132
"except ImportError",
133133
"\\.\\.\\.",
134-
"raise NotImplementedError()"
134+
"raise NotImplementedError()",
135135
]
136136

137137
# https://mypy.readthedocs.io/en/stable/config_file.html
@@ -144,11 +144,11 @@ enable_error_code = ["ignore-without-code", "redundant-expr", "truthy-bool"]
144144
warn_unreachable = true
145145

146146
[[tool.mypy.overrides]]
147-
module = "anywidget.widget" # makes heavy use of traitlets, which is not typed
147+
module = "anywidget.widget" # makes heavy use of traitlets, which is not typed
148148
disallow_untyped_calls = false
149149

150150
[[tool.mypy.overrides]]
151-
module = "anywidget._cellmagic" # makes heavy use of IPython, which is not typed
151+
module = "anywidget._cellmagic" # makes heavy use of IPython, which is not typed
152152
disallow_untyped_calls = false
153153

154154
[[tool.mypy.overrides]]

tests/test_descriptor.py

Lines changed: 13 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,8 @@
1-
from __future__ import annotations
2-
1+
import pathlib
32
import time
43
import weakref
54
from dataclasses import dataclass
6-
from typing import TYPE_CHECKING, Callable, ClassVar, Generator
5+
from typing import TYPE_CHECKING, Callable, ClassVar, Generator, Set, Union
76
from unittest.mock import MagicMock, patch
87

98
import anywidget._descriptor
@@ -15,15 +14,11 @@
1514
ReprMimeBundle,
1615
)
1716
from anywidget._file_contents import FileContents
17+
from anywidget._protocols import AnywidgetProtocol
1818
from anywidget._util import _WIDGET_MIME_TYPE
19+
from ipykernel.comm import Comm
1920
from watchfiles import Change
2021

21-
if TYPE_CHECKING:
22-
import pathlib
23-
24-
from anywidget._protocols import AnywidgetProtocol
25-
from ipykernel.comm import Comm
26-
2722

2823
class MockComm(MagicMock):
2924
# The only thing we need to do is to be able to relay messages back to
@@ -82,7 +77,7 @@ class Foo:
8277
_repr_mimebundle_ = MimeBundleDescriptor(autodetect_observer=False)
8378
value: int = val
8479

85-
def _get_anywidget_state(self, include: set[str] | None): # noqa: ANN202, ARG002
80+
def _get_anywidget_state(self, include: Union[Set[str], None]): # noqa: ANN202, ARG002
8681
return {"value": self.value}
8782

8883
def __repr__(self) -> str:
@@ -122,7 +117,7 @@ def test_state_setter(mock_comm: MagicMock) -> None:
122117
class Foo:
123118
_repr_mimebundle_ = MimeBundleDescriptor(autodetect_observer=False)
124119

125-
def _get_anywidget_state(self, include: set[str] | None): # noqa: ANN202, ARG002
120+
def _get_anywidget_state(self, include: Union[Set[str], None]): # noqa: ANN202, ARG002
126121
return {}
127122

128123
def _set_anywidget_state(self, state) -> None: # noqa: ANN001
@@ -142,7 +137,7 @@ def test_state_setter_binary(mock_comm: MagicMock) -> None:
142137
class Foo:
143138
_repr_mimebundle_ = MimeBundleDescriptor(autodetect_observer=False)
144139

145-
def _get_anywidget_state(self, include: set[str] | None): # noqa: ANN202, ARG002
140+
def _get_anywidget_state(self, include: Union[Set[str], None]): # noqa: ANN202, ARG002
146141
return {}
147142

148143
def _set_anywidget_state(self, state: dict) -> None:
@@ -168,7 +163,7 @@ def test_comm_cleanup() -> None:
168163
class Foo:
169164
_repr_mimebundle_ = MimeBundleDescriptor(autodetect_observer=False)
170165

171-
def _get_anywidget_state(self, include: set[str] | None): # noqa: ANN202, ARG002
166+
def _get_anywidget_state(self, include: Union[Set[str], None]): # noqa: ANN202, ARG002
172167
return {}
173168

174169
foo = Foo()
@@ -192,7 +187,7 @@ def test_detect_observer() -> None:
192187
class Foo:
193188
_repr_mimebundle_ = MimeBundleDescriptor()
194189

195-
def _get_anywidget_state(self, include: set[str] | None): # noqa: ANN202, ARG002
190+
def _get_anywidget_state(self, include: Union[Set[str], None]): # noqa: ANN202, ARG002
196191
return {}
197192

198193
with pytest.warns(UserWarning, match="Could not find a notifier"):
@@ -208,7 +203,7 @@ class Foo:
208203
_repr_mimebundle_ = MimeBundleDescriptor(autodetect_observer=False)
209204
value: int = 1
210205

211-
def _get_anywidget_state(self, include: set[str] | None): # noqa: ANN202, ARG002
206+
def _get_anywidget_state(self, include: Union[Set[str], None]): # noqa: ANN202, ARG002
212207
return {"value": self.value}
213208

214209
with pytest.warns(UserWarning, match=".*is not weakrefable"):
@@ -340,7 +335,7 @@ class Foo:
340335
_repr_mimebundle_ = MimeBundleDescriptor(_esm=esm, autodetect_observer=False)
341336
value: int = 1
342337

343-
def _get_anywidget_state(self, include: set[str] | None): # noqa: ANN202, ARG002
338+
def _get_anywidget_state(self, include: Union[Set[str], None]): # noqa: ANN202, ARG002
344339
return {"value": self.value}
345340

346341
file_contents = Foo._repr_mimebundle_._extra_state["_esm"]
@@ -388,7 +383,7 @@ class Foo:
388383
_repr_mimebundle_ = MimeBundleDescriptor(bar=bar, autodetect_observer=False)
389384
value: int = 1
390385

391-
def _get_anywidget_state(self, include: set[str] | None): # noqa: ANN202, ARG002
386+
def _get_anywidget_state(self, include: Union[Set[str], None]): # noqa: ANN202, ARG002
392387
return {"value": self.value}
393388

394389
file_contents = Foo._repr_mimebundle_._extra_state["bar"]
@@ -415,7 +410,7 @@ class Foo:
415410
autodetect_observer=False,
416411
)
417412

418-
def _get_anywidget_state(self, include: set[str] | None): # noqa: ANN202, ARG002
413+
def _get_anywidget_state(self, include: Union[Set[str], None]): # noqa: ANN202, ARG002
419414
return {}
420415

421416
foo = Foo()

0 commit comments

Comments
 (0)