Skip to content

Commit 6c0e885

Browse files
pavel-kirienkosongmeomaksimdrachov
authored
Fix CI, update test dependencies, and remove the compile command (#120)
Closes #63 Closes #95 --------- Co-authored-by: Song Meo <[email protected]> Co-authored-by: maksimdrachov <[email protected]>
1 parent 3a22dd4 commit 6c0e885

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

56 files changed

+231
-867
lines changed

.github/workflows/test-and-release.yml

Lines changed: 38 additions & 55 deletions
Original file line numberDiff line numberDiff line change
@@ -1,91 +1,74 @@
1-
name: 'Test and release Yakut'
1+
name: 'Test & Release'
22
on: [ push, pull_request ]
33

4-
# Ensures that only one workflow is running at a time
5-
concurrency:
6-
group: ${{ github.workflow_sha }}
7-
cancel-in-progress: true
8-
94
jobs:
10-
yakut-test:
11-
name: Test Yakut
5+
test:
6+
name: Test
127
# https://docs.github.com/en/webhooks/webhook-events-and-payloads?actionType=edited#pull_request
138
if: (github.event_name == 'push') || github.event.pull_request.head.repo.fork
149
strategy:
1510
fail-fast: false
1611
matrix:
17-
# The Windows NPcap runner is an ordinary Windows machine with the NPcap driver installed manually.
18-
# We chose to do it this way because NPcap driver installation requires a reboot, which is difficult to
19-
# automate. The NPcap driver is required for the Cyphal/UDP transport tests to work.
20-
os: [ubuntu-22.04, windows-2019-npcap]
21-
python: ['3.8', '3.9', '3.10', '3.11']
22-
exclude: # We don't test Windows with old Python versions because it takes too much effort.
23-
- os: windows-2019-npcap
24-
python: 3.8
25-
- os: windows-2019-npcap
26-
python: 3.9
12+
os: [ ubuntu-latest ]
13+
py: [ '3.10', '3.11', '3.12', '3.13' ]
14+
# On Windows, we select the configurations we test manually because we only have a few runners,
15+
# and because the infrastructure is hard to maintain using limited resources.
16+
include:
17+
- { os: win-pcap, py: '3.12' }
2718
runs-on: ${{ matrix.os }}
19+
env:
20+
FORCE_COLOR: 1
2821
steps:
29-
- name: Check out
30-
uses: actions/checkout@v3
31-
32-
- name: Install Python3
33-
uses: actions/setup-python@v4
22+
- uses: actions/checkout@v4
3423
with:
35-
python-version: ${{ matrix.python }}
24+
submodules: true
3625

37-
- name: Log Python version
38-
run: python --version
26+
- uses: actions/setup-python@v5
27+
with:
28+
python-version: ${{ matrix.py }}
3929

40-
- name: Install dependencies
30+
- name: Configure GNU/Linux
31+
if: ${{ runner.os == 'Linux' }}
4132
# language=bash
4233
run: |
43-
if [ "$RUNNER_OS" == "Linux" ]; then
44-
sudo apt-get --ignore-missing update || true
45-
sudo apt-get install -y linux-*-extra-$(uname -r) ncat
46-
sudo apt-get install -y libsdl2-2.0-0 # For PySDL2. On Windows/macOS the binaries are pulled from PyPI.
47-
sudo apt-get install -y libasound2-dev # For RtMidi.
48-
fi
49-
git submodule update --init --recursive
50-
python -m pip install --upgrade pip setuptools nox
51-
shell: bash
34+
python --version
35+
sudo apt-get --ignore-missing update || true
36+
sudo apt-get install -y linux-*-extra-$(uname -r) ncat
37+
sudo apt-get install -y libsdl2-2.0-0 # For PySDL2. On Windows/macOS the binaries are pulled from PyPI.
38+
sudo apt-get install -y libasound2-dev # For RtMidi.
5239
53-
- name: Run build and test
54-
# language=bash
55-
run: |
56-
nox --non-interactive --session test --python ${{ matrix.python }}
57-
nox --non-interactive --session lint
58-
shell: bash
59-
env:
60-
FORCE_COLOR: 1
40+
# Only one statement per step to ensure the error codes are not ignored by PowerShell.
41+
- run: python -m pip install --upgrade attrs pip setuptools nox
42+
- run: nox --non-interactive --session test --python ${{ matrix.py }}
43+
- run: nox --non-interactive --session lint
6144

62-
- name: Upload diagnostics
63-
uses: actions/upload-artifact@v3
45+
- uses: actions/upload-artifact@v4
6446
if: (success() || failure())
6547
with:
6648
# The matrix is shown for convenience but this is fragile because the values may not be string-convertible.
6749
# Shall it break one day, feel free to remove the matrix from here.
68-
# The job status is per matrix item, which is super convenient.
6950
name: ${{github.job}}-#${{strategy.job-index}}-${{job.status}}-${{join(matrix.*, ',')}}
7051
path: "**/*.log"
71-
retention-days: 7
52+
retention-days: 90
53+
include-hidden-files: true
7254

73-
yakut-release:
74-
name: Release Yakut
55+
release:
56+
name: Release
7557
runs-on: ubuntu-latest
7658
if: >
7759
(github.event_name == 'push') &&
7860
(contains(github.event.head_commit.message, '#release') || contains(github.ref, '/main'))
79-
needs: yakut-test
61+
needs: test
8062
steps:
8163
- name: Check out
82-
uses: actions/checkout@v3
64+
uses: actions/checkout@v4
65+
with:
66+
submodules: true
8367

8468
- name: Create distribution wheel
8569
# language=bash
8670
run: |
87-
git submodule update --init --recursive
88-
python -m pip install --upgrade pip setuptools wheel twine
71+
python -m pip install --upgrade packaging pip setuptools wheel twine
8972
python setup.py sdist bdist_wheel
9073
9174
- name: Get release version
@@ -99,7 +82,7 @@ jobs:
9982
TWINE_PASSWORD: ${{ secrets.PYPI_API_TOKEN_YAKUT }}
10083

10184
- name: Push version tag
102-
uses: mathieudutour/github-tag-action@v6.1
85+
uses: mathieudutour/github-tag-action@v6.2
10386
with:
10487
github_token: ${{ secrets.GITHUB_TOKEN }}
10588
custom_tag: ${{ env.yakut_version }}

.gitignore

Lines changed: 0 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -53,6 +53,3 @@ coverage.xml
5353

5454
# Compiled namespaces
5555
.*compiled
56-
/uavcan/
57-
/reg/
58-
/sirius_cyber_corp/

.gitmodules

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
[submodule "tests/deps/public_regulated_data_types"]
2+
path = tests/deps/public_regulated_data_types
3+
url = https://github.com/OpenCyphal/public_regulated_data_types

CONTRIBUTING.md

Lines changed: 3 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -55,7 +55,7 @@ A more interactive approach is as follows:
5555
3. Change directory to `.nox/test-3-8/tmp`, here substitute `test-3-8` for the directory you have.
5656
This is one of the environments that Nox creates for testing.
5757
4. Run `source ../bin/activate` to activate the virtualenv.
58-
5. `export PYTHONPATH=.compiled/`
58+
5. Optionally: `export PYCYPHAL_PATH=...compiled/`
5959
6. Run specific commands you need:
6060
`pytest ../../../yakut/whatever`, `mypy --strict ../../../yakut ../../../tests`, etc.
6161

@@ -74,11 +74,10 @@ To look for manual tests in the codebase, please search for `def _main` under `t
7474

7575
We recommend [JetBrains PyCharm](https://www.jetbrains.com/pycharm/) for development.
7676

77-
The test suite stores compiled DSDL into `.compiled/` in the current working directory
78-
(when using Nox, the current working directory may be under a virtualenv private directory).
77+
The test suite stores compiled DSDL into whatever is pointed to by `PYCYPHAL_PATH`;
78+
the Noxfile overrides `PYCYPHAL_PATH` with a directory inside the venv.
7979
Make sure to mark it as a source directory to enable code completion and type analysis in the IDE
8080
(for PyCharm: right click -> Mark Directory As -> Sources Root).
81-
Alternatively, you can just compile DSDL manually directly in the project root.
8281

8382
Configure the IDE to run Black on save.
8483
See the Black documentation for integration instructions.

README.md

Lines changed: 3 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
# Yakut
1+
# Yakut – Cyphal CLI tool
22

33
<!--suppress CheckImageSize, HtmlDeprecatedAttribute -->
44
<img src="/docs/opencyphal-favicon-512.png" alt="OpenCyphal logo" width=128 align=right>
@@ -23,8 +23,6 @@ Afterward do endeavor to read the docs: **`yakut --help`**
2323

2424
Check for new versions every now and then: **`pip install --upgrade yakut`**
2525

26-
Installation & configuration screencasts are available for [Windows](https://forum.opencyphal.org/t/screencast-of-installing-configuring-yakut/1197/2?u=pavel.kirienko), [GNU/Linux](https://forum.opencyphal.org/t/screencast-of-installing-configuring-yakut/1197/1?u=pavel.kirienko), and [macOS](https://www.youtube.com/watch?v=dQw4w9WgXcQ).
27-
2826
### Additional third-party tools
2927

3028
Since Yakut heavily relies on YAML/JSON documents exchanged via stdin/stdout, [**`jq`**](https://stedolan.github.io/jq/) is often needed for any non-trivial usage of the tool, so consider installing it as well. Users of GNU/Linux will likely find it in the default software repositories (`pacman -S jq`, `apt install jq`, etc.).
@@ -33,9 +31,9 @@ Since Yakut heavily relies on YAML/JSON documents exchanged via stdin/stdout, [*
3331

3432
Transport layer inspection tools:
3533

34+
- [Wireshark](https://www.wireshark.org/) with [Cyphal plugins](https://github.com/OpenCyphal/wireshark_plugins)
35+
(n.b.: some versions of Wireshark may label Cyphal/CAN captures as UAVCAN/CAN due to rebranding).
3636
- Cyphal/CAN on GNU/Linux (candump, canbusload, etc.): [`can-utils`](https://github.com/linux-can/can-utils)
37-
- Cyphal/UDP or Cyphal/CAN: [Wireshark](https://www.wireshark.org/)
38-
(n.b.: Wireshark might label Cyphal captures as UAVCAN due to rebranding)
3937

4038
## Invoking commands
4139

noxfile.py

Lines changed: 18 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
# Copyright (c) 2020 OpenCyphal
1+
# Copyright (c) OpenCyphal
22
# This software is distributed under the terms of the MIT License.
33
# Author: Pavel Kirienko <[email protected]>
44
# type: ignore
@@ -14,8 +14,13 @@
1414
DEPS_DIR = ROOT_DIR / "tests" / "deps"
1515
assert DEPS_DIR.is_dir(), "Invalid configuration"
1616

17+
CYPHAL_PATH = [
18+
DEPS_DIR / "public_regulated_data_types",
19+
ROOT_DIR / "tests" / "custom_data_types",
20+
]
1721

18-
PYTHONS = ["3.8", "3.9", "3.10", "3.11"]
22+
23+
PYTHONS = ["3.10", "3.11", "3.12", "3.13"]
1924

2025

2126
@nox.session(python=False)
@@ -50,9 +55,9 @@ def test(session):
5055

5156
# Now we can install dependencies for the full integration test suite.
5257
session.install(
53-
"pytest ~= 7.4",
54-
"pytest-asyncio ~= 0.21.0",
55-
"coverage ~= 7.4",
58+
"pytest ~= 8.3",
59+
"pytest-asyncio ~= 0.26.0",
60+
"coverage ~= 7.8",
5661
)
5762

5863
# The test suite generates a lot of temporary files, so we change the working directory.
@@ -82,13 +87,12 @@ def test(session):
8287
*session.posargs,
8388
env={
8489
"PYTHONPATH": str(DEPS_DIR),
85-
"PATH": os.pathsep.join([session.env["PATH"], str(DEPS_DIR)]),
90+
"PATH": os.pathsep.join([os.environ["PATH"], str(DEPS_DIR)]),
91+
"CYPHAL_PATH": os.pathsep.join(map(str, CYPHAL_PATH)),
92+
"PYCYPHAL_PATH": str(tmp_dir / ".compiled"),
93+
"PYCYPHAL_LOGLEVEL": "ERROR",
8694
},
8795
)
88-
89-
# The coverage threshold is intentionally set low for interactive runs because when running locally
90-
# in a reused virtualenv the DSDL compiler run may be skipped to save time, resulting in a reduced coverage.
91-
# Some features are not available on Windows so the coverage threshold is set low for it.
9296
if session.posargs or session.interactive or sys.platform.startswith("win"):
9397
fail_under = 1
9498
else:
@@ -104,14 +108,14 @@ def test(session):
104108
# 1. It requires access to the code generated by the test suite.
105109
# 2. It has to be run separately per Python version we support.
106110
# If the interpreter is not CPython, this may need to be conditionally disabled.
107-
session.install("mypy ~= 1.8")
108-
session.run("mypy", "--strict", *map(str, src_dirs))
111+
session.install("mypy ~= 1.15.0")
112+
session.run("mypy", *map(str, src_dirs))
109113

110114

111115
@nox.session(reuse_venv=True)
112116
def lint(session):
113-
session.install("pylint ~= 3.0.3")
117+
session.install("pylint ~= 3.3.7")
114118
session.run("pylint", "yakut", "tests")
115119

116-
session.install("black ~= 23.12")
120+
session.install("black ~= 25.1")
117121
session.run("black", "--check", ".")

setup.cfg

Lines changed: 10 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -48,7 +48,7 @@ zip_safe = False
4848
include_package_data = True
4949
packages = find:
5050
install_requires =
51-
pycyphal[transport-udp,transport-serial,transport-can-pythoncan] ~= 1.8
51+
pycyphal[transport-udp,transport-serial,transport-can-pythoncan] ~= 1.20
5252
ruamel.yaml < 0.18
5353
requests ~= 2.27
5454
simplejson ~= 3.17
@@ -100,9 +100,10 @@ log_file = pytest.log
100100
log_file_level = DEBUG
101101
# Unraisable exceptions are filtered because PyTest yields false-positives coming from PyCyphal.
102102
addopts = --doctest-modules -v -p no:unraisableexception
103-
asyncio_mode = auto
104103
filterwarnings =
105104
ignore:.*SDL2.*:UserWarning
105+
asyncio_mode = auto
106+
asyncio_default_fixture_loop_scope = function
106107

107108
# ---------------------------------------- MYPY ----------------------------------------
108109
[mypy]
@@ -114,15 +115,19 @@ disallow_untyped_defs = True
114115
check_untyped_defs = True
115116
no_implicit_optional = True
116117
warn_redundant_casts = True
117-
warn_unused_ignores = True
118+
warn_unused_ignores = False
118119
show_error_context = True
119-
strict_equality = True
120+
strict_equality = False
121+
strict = False
120122
implicit_reexport = False
121123
# We don't want MyPy to go checking generated code and its dependencies.
122124
follow_imports = silent
123125
mypy_path =
124126
.compiled
125127

128+
[mypy-nunavut_support]
129+
ignore_errors = True
130+
126131
[mypy-pytest.*]
127132
ignore_missing_imports = True
128133

@@ -167,6 +172,7 @@ exclude_lines =
167172
# ---------------------------------------- PYLINT ----------------------------------------
168173
[pylint.MASTER]
169174
fail-under=9.9
175+
ignore-paths=^.*/\.compiled/.*$
170176

171177
[pylint.MESSAGES CONTROL]
172178
# Valid levels: HIGH, INFERENCE, INFERENCE_FAILURE, UNDEFINED.

tests/cmd/accommodate.py

Lines changed: 1 addition & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -4,22 +4,18 @@
44

55
from __future__ import annotations
66
import time
7-
import typing
87
from tests.subprocess import Subprocess, execute_cli
9-
from tests.dsdl import OUTPUT_DIR
108
from tests.transport import TransportFactory
119

1210

13-
def _unittest_accommodate_swarm(transport_factory: TransportFactory, compiled_dsdl: typing.Any) -> None:
14-
_ = compiled_dsdl
11+
def _unittest_accommodate_swarm(transport_factory: TransportFactory) -> None:
1512
# We spawn a lot of processes here, which might strain the test system a little, so beware. I've tested it
1613
# with 120 processes and it made my workstation (24 GB RAM ~4 GHz Core i7) struggle to the point of being
1714
# unable to maintain sufficiently real-time operation for the test to pass. Hm.
1815
used_node_ids = list(range(5))
1916
pubs = [
2017
Subprocess.cli(
2118
f"--transport={transport_factory(idx).expression}",
22-
f"--path={OUTPUT_DIR}",
2319
"pub",
2420
"--period=0.4",
2521
"--count=60",
@@ -29,7 +25,6 @@ def _unittest_accommodate_swarm(transport_factory: TransportFactory, compiled_ds
2925
time.sleep(5) # Some time is required for the nodes to start.
3026
_, stdout, _ = execute_cli(
3127
"-v",
32-
f"--path={OUTPUT_DIR}",
3328
f"--transport={transport_factory(None).expression}",
3429
"accommodate",
3530
timeout=100.0,
@@ -42,7 +37,6 @@ def _unittest_accommodate_swarm(transport_factory: TransportFactory, compiled_ds
4237
def _unittest_accommodate_loopback() -> None:
4338
_, stdout, _ = execute_cli(
4439
"-v",
45-
f"--path={OUTPUT_DIR}",
4640
"accommodate",
4741
timeout=30.0,
4842
environment_variables={"YAKUT_TRANSPORT": "Loopback(None),Loopback(None)"},
@@ -53,7 +47,6 @@ def _unittest_accommodate_loopback() -> None:
5347
def _unittest_accommodate_udp_localhost() -> None:
5448
_, stdout, _ = execute_cli(
5549
"-v",
56-
f"--path={OUTPUT_DIR}",
5750
"accommodate",
5851
timeout=30.0,
5952
environment_variables={"YAKUT_TRANSPORT": 'UDP("127.0.0.1",None)'},

0 commit comments

Comments
 (0)