Repository navigation
Expand file tree
/
Copy pathjustfile
More file actions
186 lines (150 loc) · 7.38 KB
/
Copy pathjustfile
File metadata and controls
186 lines (150 loc) · 7.38 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
set positional-arguments := true
export CARGO_TERM_COLOR := "always"
# On Windows, ensure shebang recipes use Git Bash, not the WSL `bash` in System32 (see #109).
# Git Bash's dir is derived from wherever `git` resolves on PATH, not a hardcoded install path.
export PATH := if os() == "windows" { (parent_directory(parent_directory(require("git.exe"))) / "bin") + ";" + env_var("PATH") } else { env_var("PATH") }
# Default command is no subcommand given to list available commands
default:
@just --list
# development install with dependencies (optionally specify extras, e.g. `just install daq`)
install *extras:
#!/usr/bin/env bash
if [ -z "{{ extras }}" ]; then
uv sync
elif [ "{{ extras }}" = "all" ]; then
uv sync --all-extras
else
args=""
for extra in {{ extras }}; do
args="$args --extra $extra"
done
uv sync $args
fi
# Enter into the python interpreter with all dependencies loaded
python *args:
uv run python "$@"
# run python unit tests
test-python:
uv run pytest
# open the example notebooks in JupyterLab; open one with Open With → Jupytext Notebook
notebook *args:
uv run --with jupyterlab --with jupytext jupyter lab examples/notebooks "$@"
# run every example notebook from top to bottom, failing on the first cell that raises
test-notebooks:
for nb in examples/notebooks/*.md; do echo "$nb"; uv run --with jupytext --with nbconvert --with ipykernel sh -c 'jupytext --from myst --to ipynb --output - "$1" | jupyter nbconvert --stdin --stdout --to notebook --execute --log-level=WARN > /dev/null' _ "$nb" || exit 1; done
# run Rust library, integration, and doc tests for the workspace
test-rust:
cargo nextest run --workspace --all-features --all-targets
cargo test --workspace --all-features --doc
# run all python and Rust tests plus EtherNet/IP packaging checks
test: test-rust test-python eip-test
# check static typing
check-types:
uv run mypy
# check static typing across all supported python versions
check-types-all:
uv run mypy --python-version 3.14
uv run mypy --python-version 3.13
uv run mypy --python-version 3.12
uv run mypy --python-version 3.11
# check code formatting | fix with `just fix-format`
check-format:
uv run ruff format --check
# check import ordering | fix with `just fix-imports`
check-imports:
uv run ruff check
# run all python static analysis checks
check-python: check-format check-types check-imports
# check Rust formatting, lints, and lockfile | fix with `just fix-rust`
check-rust:
cargo +nightly fmt --all --check
cargo clippy --locked --all-features --all-targets --workspace -- -D warnings
# run all static analysis checks
check: check-python check-rust
# fixes out-of-order imports (note: mutates the code)
fix-imports:
uv run ruff check --fix
# fixes code formatting (note: mutates the code)
fix-format:
uv run ruff format
# fix python imports and formatting
fix-python: fix-format fix-imports
# fixes Rust lints and code formatting (note: mutates the code)
fix-rust:
cargo clippy --fix --allow-dirty --allow-staged --all-targets --all-features --workspace
cargo +nightly fmt --all
# fix imports and formatting
fix: fix-python fix-rust
# run all python tests and checks
verify-python: install test-python check-python
# run all Rust tests and checks
verify-rust: test-rust check-rust
# run all tests and checks
verify: install test check
# clean up uv environments
clean:
uv cache clean
# build all packages as wheels
build:
uv build --wheel --all-packages
# the docs group is empty below Python 3.12, so sphinx-build would fail with an opaque "not found"
_check-docs-python:
uv run python -c "import sys; sys.exit(0 if sys.version_info >= (3, 12) else f'The docs toolchain needs Python >= 3.12 in the project environment (found {sys.version.split()[0]}). Recreate it with: uv sync --python 3.13 --group docs')"
# build the docs site (guides + API reference) into docs/_build/dirhtml, running the example notebooks; warnings fail the build
# OBJC_DISABLE_INITIALIZE_FORK_SAFETY: on macOS, -j forks Sphinx workers after notebook execution has started threads,
# and the Objective-C runtime aborts the child; the variable has no effect on other platforms
build-docs: _check-docs-python
OBJC_DISABLE_INITIALIZE_FORK_SAFETY=YES uv run --group docs sphinx-build -E -W --keep-going -j auto -b dirhtml docs docs/_build/dirhtml
# live-preview the docs on http://127.0.0.1:8000, rebuilding on page, example, or docstring changes
serve-docs: _check-docs-python
OBJC_DISABLE_INITIALIZE_FORK_SAFETY=YES uv run --group docs --with sphinx-autobuild sphinx-autobuild -j auto -b dirhtml docs docs/_build/dirhtml --watch instro --watch packages --watch examples --ignore "*/docs/examples/*"
# run EtherNet/IP integration tests against the live PLC at 10.123.1.199:44818
eip-live-test:
#!/usr/bin/env bash
set -euo pipefail
export INSTRO_EIP_PLC_ENDPOINT=10.123.1.199:44818
export INSTRO_EIP_ROUTE_PATH_SLOTS=0
export INSTRO_EIP_TARGET_L32E=1
uv run --reinstall-package instro-ethernetip --with-editable . pytest -m hardware tests/ethernetip/test_ethernetip_bindings.py -q
# clean build of the EtherNet/IP Python bindings (sdist + wheel)
# uv selects the workspace package via --package, then uses that package's
# [build-system] backend; for instro-ethernetip that backend is maturin.
eip-build:
uv build --package instro-ethernetip
# build the EtherNet/IP sdist and verify it contains source-build inputs
eip-sdist-smoke-test:
#!/usr/bin/env bash
set -euo pipefail
dist_dir="$(mktemp -d)"
trap 'rm -rf "$dist_dir"' EXIT
uv build --sdist --package instro-ethernetip --out-dir "$dist_dir"
sdists=("$dist_dir"/instro_ethernetip-*.tar.gz)
uv run python tests/ethernetip/check_ethernetip_sdist.py sdist "${sdists[0]}"
# install the built wheel into an isolated environment and verify the private native module
eip-wheel-smoke-test:
#!/usr/bin/env bash
set -euo pipefail
# Use an isolated wheel dir so stale dist/ artifacts cannot be selected.
wheel_dir="$(mktemp -d)"
trap 'rm -rf "$wheel_dir"' EXIT
# Build the platform-specific native extension wheel. This wheel provides
# instro.ethernetip._ethernetip, the private PyO3 module loaded at import time.
uv build --wheel --package instro-ethernetip --out-dir "$wheel_dir"
wheel="$(find "$wheel_dir" -maxdepth 1 -name 'instro_ethernetip-*.whl' -print -quit)"
if [ -z "$wheel" ]; then
echo "No instro-ethernetip wheel found in $wheel_dir" >&2
exit 1
fi
uv_run_args=(
--isolated # Ignore the workspace virtual environment.
--no-dev # Avoid default dev dependencies that can shadow the wheel.
--no-cache # Avoid stale same-version wheel contents.
--with-editable . # Use this checkout's up-to-date instro dependency.
--with "$wheel" # Install the freshly built native extension wheel.
--with mypy # Provide the type checker used by the smoke script.
)
INSTRO_EIP_WHEEL="$wheel" uv run "${uv_run_args[@]}" python tests/ethernetip/ethernetip_wheel_smoke.py
# Full EIP test suite: wheel smoke test, Rust/Python bindings, and cpppo integration
eip-test: eip-sdist-smoke-test eip-wheel-smoke-test
cargo nextest run --all-features --all-targets -p instro-ethernetip
uv run --reinstall-package instro-ethernetip --with-editable . pytest tests/ethernetip/test_ethernetip_bindings.py -q