oxiserial 0.1.0__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- oxiserial-0.1.0/.claude/settings.json +58 -0
- oxiserial-0.1.0/.github/workflows/build-wheels.yaml +170 -0
- oxiserial-0.1.0/.github/workflows/ci.yaml +50 -0
- oxiserial-0.1.0/.github/workflows/run-tests.yaml +141 -0
- oxiserial-0.1.0/.gitignore +80 -0
- oxiserial-0.1.0/CLAUDE.md +51 -0
- oxiserial-0.1.0/Cargo.lock +484 -0
- oxiserial-0.1.0/Cargo.toml +38 -0
- oxiserial-0.1.0/LICENSE +26 -0
- oxiserial-0.1.0/LICENSES/pyserial.txt +39 -0
- oxiserial-0.1.0/PKG-INFO +125 -0
- oxiserial-0.1.0/README.md +103 -0
- oxiserial-0.1.0/pyproject.toml +74 -0
- oxiserial-0.1.0/python/oxiserial/__init__.py +2 -0
- oxiserial-0.1.0/python/oxiserial/__init__.pyi +479 -0
- oxiserial-0.1.0/python/oxiserial/_testing.pyi +41 -0
- oxiserial-0.1.0/python/oxiserial/aio.pyi +212 -0
- oxiserial-0.1.0/python/oxiserial/py.typed +0 -0
- oxiserial-0.1.0/python/oxiserial/tools/__init__.pyi +5 -0
- oxiserial-0.1.0/python/oxiserial/tools/list_ports.pyi +76 -0
- oxiserial-0.1.0/src/aio.rs +131 -0
- oxiserial-0.1.0/src/backend/mock.rs +295 -0
- oxiserial-0.1.0/src/backend/native.rs +428 -0
- oxiserial-0.1.0/src/backend/overlapped.rs +444 -0
- oxiserial-0.1.0/src/backend.rs +67 -0
- oxiserial-0.1.0/src/errors.rs +165 -0
- oxiserial-0.1.0/src/future.rs +424 -0
- oxiserial-0.1.0/src/lib.rs +102 -0
- oxiserial-0.1.0/src/list_ports.rs +223 -0
- oxiserial-0.1.0/src/port.rs +830 -0
- oxiserial-0.1.0/src/runtime.rs +39 -0
- oxiserial-0.1.0/src/serial.rs +784 -0
- oxiserial-0.1.0/src/settings.rs +177 -0
- oxiserial-0.1.0/src/testing.rs +65 -0
- oxiserial-0.1.0/tests/conftest.py +64 -0
- oxiserial-0.1.0/tests/test_aio.py +151 -0
- oxiserial-0.1.0/tests/test_future.py +329 -0
- oxiserial-0.1.0/tests/test_import.py +7 -0
- oxiserial-0.1.0/tests/test_list_ports.py +61 -0
- oxiserial-0.1.0/tests/test_real_ports.py +152 -0
- oxiserial-0.1.0/tests/test_serial.py +382 -0
- oxiserial-0.1.0/tests/test_signatures.py +16 -0
- oxiserial-0.1.0/tests/typing/check_types.py +26 -0
- oxiserial-0.1.0/uv.lock +473 -0
|
@@ -0,0 +1,58 @@
|
|
|
1
|
+
{
|
|
2
|
+
"permissions": {
|
|
3
|
+
"allow": [
|
|
4
|
+
"Bash(uv run:*)",
|
|
5
|
+
"Bash(uv sync:*)",
|
|
6
|
+
"Bash(cargo fmt:*)",
|
|
7
|
+
"Bash(cargo clippy:*)",
|
|
8
|
+
"Bash(cargo test:*)",
|
|
9
|
+
"Bash(cargo build:*)",
|
|
10
|
+
"Bash(cargo check:*)",
|
|
11
|
+
"Bash(git commit:*)",
|
|
12
|
+
"Bash(git status:*)",
|
|
13
|
+
"Bash(git diff:*)",
|
|
14
|
+
"Bash(git log:*)",
|
|
15
|
+
"Bash(git show:*)",
|
|
16
|
+
"Bash(git rev-parse:*)",
|
|
17
|
+
"Bash(git branch:*)",
|
|
18
|
+
"Bash(git merge-base:*)",
|
|
19
|
+
"Bash(git ls-files:*)",
|
|
20
|
+
"Bash(git add:*)",
|
|
21
|
+
"Bash(gh pr view:*)",
|
|
22
|
+
"Bash(ls:*)",
|
|
23
|
+
"Bash(cat:*)",
|
|
24
|
+
"Bash(echo:*)",
|
|
25
|
+
"Bash(printf:*)",
|
|
26
|
+
"Bash(grep:*)",
|
|
27
|
+
"Bash(sed -n:*)",
|
|
28
|
+
"Bash(head:*)",
|
|
29
|
+
"Bash(tail:*)",
|
|
30
|
+
"Bash(find:*)",
|
|
31
|
+
"Bash(wc:*)",
|
|
32
|
+
"Bash(mkdir:*)",
|
|
33
|
+
"Edit",
|
|
34
|
+
"Write"
|
|
35
|
+
],
|
|
36
|
+
"deny": [
|
|
37
|
+
"Bash(git push:*)",
|
|
38
|
+
"Bash(git push --force:*)",
|
|
39
|
+
"Bash(git reset --hard:*)",
|
|
40
|
+
"Bash(rm -rf:*)",
|
|
41
|
+
"Bash(rmdir /s:*)",
|
|
42
|
+
"Bash(Remove-Item:*)",
|
|
43
|
+
"Bash(gh pr merge:*)",
|
|
44
|
+
"Read(./.env)",
|
|
45
|
+
"Read(./.env.*)"
|
|
46
|
+
]
|
|
47
|
+
},
|
|
48
|
+
"hooks": {
|
|
49
|
+
"PostToolUse": [
|
|
50
|
+
{
|
|
51
|
+
"matcher": "Edit|Write",
|
|
52
|
+
"hooks": [
|
|
53
|
+
{ "type": "command", "command": "uv run ruff format python tests && uv run ruff check --fix python tests" }
|
|
54
|
+
]
|
|
55
|
+
}
|
|
56
|
+
]
|
|
57
|
+
}
|
|
58
|
+
}
|
|
@@ -0,0 +1,170 @@
|
|
|
1
|
+
name: Build Wheels
|
|
2
|
+
|
|
3
|
+
on:
|
|
4
|
+
workflow_call:
|
|
5
|
+
|
|
6
|
+
jobs:
|
|
7
|
+
linux:
|
|
8
|
+
runs-on: ${{ matrix.platform.runner }}
|
|
9
|
+
strategy:
|
|
10
|
+
matrix:
|
|
11
|
+
platform:
|
|
12
|
+
- runner: ubuntu-22.04
|
|
13
|
+
target: x86_64
|
|
14
|
+
- runner: ubuntu-22.04
|
|
15
|
+
target: x86
|
|
16
|
+
- runner: ubuntu-22.04
|
|
17
|
+
target: aarch64
|
|
18
|
+
- runner: ubuntu-22.04
|
|
19
|
+
target: armv7
|
|
20
|
+
- runner: ubuntu-22.04
|
|
21
|
+
target: s390x
|
|
22
|
+
- runner: ubuntu-22.04
|
|
23
|
+
target: ppc64le
|
|
24
|
+
steps:
|
|
25
|
+
- uses: actions/checkout@v6
|
|
26
|
+
- &set-version
|
|
27
|
+
name: Set version from tag
|
|
28
|
+
if: startsWith(github.ref, 'refs/tags/v')
|
|
29
|
+
shell: bash
|
|
30
|
+
run: |
|
|
31
|
+
# PEP 440 pre-release (1.2.0rc1) -> semver (1.2.0-rc.1); maturin maps it back.
|
|
32
|
+
v="$(echo "${GITHUB_REF_NAME#v}" | sed -E 's/(a|b|rc)([0-9]+)$/-\1.\2/')"
|
|
33
|
+
sed -i.bak -E '/^\[package\]/,/^\[/ s/^version = ".*"/version = "'"$v"'"/' Cargo.toml
|
|
34
|
+
rm Cargo.toml.bak
|
|
35
|
+
cargo update --workspace
|
|
36
|
+
- uses: actions/setup-python@v6
|
|
37
|
+
with:
|
|
38
|
+
python-version: "3.x"
|
|
39
|
+
- name: Build wheels
|
|
40
|
+
uses: PyO3/maturin-action@v1
|
|
41
|
+
with:
|
|
42
|
+
target: ${{ matrix.platform.target }}
|
|
43
|
+
args: --release --out dist -i python3.11 -i python3.14t
|
|
44
|
+
sccache: ${{ !startsWith(github.ref, 'refs/tags/') }}
|
|
45
|
+
manylinux: auto
|
|
46
|
+
- name: Upload wheels
|
|
47
|
+
uses: actions/upload-artifact@v6
|
|
48
|
+
with:
|
|
49
|
+
name: wheels-linux-${{ matrix.platform.target }}
|
|
50
|
+
path: dist
|
|
51
|
+
|
|
52
|
+
musllinux:
|
|
53
|
+
runs-on: ${{ matrix.platform.runner }}
|
|
54
|
+
strategy:
|
|
55
|
+
matrix:
|
|
56
|
+
platform:
|
|
57
|
+
- runner: ubuntu-22.04
|
|
58
|
+
target: x86_64
|
|
59
|
+
- runner: ubuntu-22.04
|
|
60
|
+
target: x86
|
|
61
|
+
- runner: ubuntu-22.04
|
|
62
|
+
target: aarch64
|
|
63
|
+
- runner: ubuntu-22.04
|
|
64
|
+
target: armv7
|
|
65
|
+
steps:
|
|
66
|
+
- uses: actions/checkout@v6
|
|
67
|
+
- *set-version
|
|
68
|
+
- uses: actions/setup-python@v6
|
|
69
|
+
with:
|
|
70
|
+
python-version: "3.x"
|
|
71
|
+
- name: Build wheels
|
|
72
|
+
uses: PyO3/maturin-action@v1
|
|
73
|
+
with:
|
|
74
|
+
target: ${{ matrix.platform.target }}
|
|
75
|
+
args: --release --out dist -i python3.11 -i python3.14t
|
|
76
|
+
sccache: ${{ !startsWith(github.ref, 'refs/tags/') }}
|
|
77
|
+
manylinux: musllinux_1_2
|
|
78
|
+
- name: Upload wheels
|
|
79
|
+
uses: actions/upload-artifact@v6
|
|
80
|
+
with:
|
|
81
|
+
name: wheels-musllinux-${{ matrix.platform.target }}
|
|
82
|
+
path: dist
|
|
83
|
+
|
|
84
|
+
windows:
|
|
85
|
+
runs-on: ${{ matrix.platform.runner }}
|
|
86
|
+
strategy:
|
|
87
|
+
matrix:
|
|
88
|
+
platform:
|
|
89
|
+
- runner: windows-latest
|
|
90
|
+
target: x64
|
|
91
|
+
python_arch: x64
|
|
92
|
+
- runner: windows-latest
|
|
93
|
+
target: x86
|
|
94
|
+
python_arch: x86
|
|
95
|
+
- runner: windows-11-arm
|
|
96
|
+
target: aarch64
|
|
97
|
+
python_arch: arm64
|
|
98
|
+
steps:
|
|
99
|
+
- uses: actions/checkout@v6
|
|
100
|
+
- *set-version
|
|
101
|
+
- uses: actions/setup-python@v6
|
|
102
|
+
id: py311
|
|
103
|
+
with:
|
|
104
|
+
python-version: "3.11"
|
|
105
|
+
architecture: ${{ matrix.platform.python_arch }}
|
|
106
|
+
- uses: actions/setup-python@v6
|
|
107
|
+
id: py314t
|
|
108
|
+
with:
|
|
109
|
+
python-version: "3.14t"
|
|
110
|
+
architecture: ${{ matrix.platform.python_arch }}
|
|
111
|
+
- name: Build wheels
|
|
112
|
+
uses: PyO3/maturin-action@v1
|
|
113
|
+
with:
|
|
114
|
+
target: ${{ matrix.platform.target }}
|
|
115
|
+
args: --release --out dist -i ${{ steps.py311.outputs.python-path }} -i ${{ steps.py314t.outputs.python-path }}
|
|
116
|
+
sccache: ${{ !startsWith(github.ref, 'refs/tags/') }}
|
|
117
|
+
- name: Upload wheels
|
|
118
|
+
uses: actions/upload-artifact@v6
|
|
119
|
+
with:
|
|
120
|
+
name: wheels-windows-${{ matrix.platform.target }}
|
|
121
|
+
path: dist
|
|
122
|
+
|
|
123
|
+
macos:
|
|
124
|
+
runs-on: ${{ matrix.platform.runner }}
|
|
125
|
+
strategy:
|
|
126
|
+
matrix:
|
|
127
|
+
platform:
|
|
128
|
+
- runner: macos-15-intel
|
|
129
|
+
target: x86_64
|
|
130
|
+
- runner: macos-latest
|
|
131
|
+
target: aarch64
|
|
132
|
+
steps:
|
|
133
|
+
- uses: actions/checkout@v6
|
|
134
|
+
- *set-version
|
|
135
|
+
- uses: actions/setup-python@v6
|
|
136
|
+
id: py311
|
|
137
|
+
with:
|
|
138
|
+
python-version: "3.11"
|
|
139
|
+
- uses: actions/setup-python@v6
|
|
140
|
+
id: py314t
|
|
141
|
+
with:
|
|
142
|
+
python-version: "3.14t"
|
|
143
|
+
- name: Build wheels
|
|
144
|
+
uses: PyO3/maturin-action@v1
|
|
145
|
+
with:
|
|
146
|
+
target: ${{ matrix.platform.target }}
|
|
147
|
+
args: --release --out dist -i ${{ steps.py311.outputs.python-path }} -i ${{ steps.py314t.outputs.python-path }}
|
|
148
|
+
sccache: ${{ !startsWith(github.ref, 'refs/tags/') }}
|
|
149
|
+
- name: Upload wheels
|
|
150
|
+
uses: actions/upload-artifact@v6
|
|
151
|
+
with:
|
|
152
|
+
name: wheels-macos-${{ matrix.platform.target }}
|
|
153
|
+
path: dist
|
|
154
|
+
|
|
155
|
+
sdist:
|
|
156
|
+
if: startsWith(github.ref, 'refs/tags/v')
|
|
157
|
+
runs-on: ubuntu-latest
|
|
158
|
+
steps:
|
|
159
|
+
- uses: actions/checkout@v6
|
|
160
|
+
- *set-version
|
|
161
|
+
- name: Build sdist
|
|
162
|
+
uses: PyO3/maturin-action@v1
|
|
163
|
+
with:
|
|
164
|
+
command: sdist
|
|
165
|
+
args: --out dist
|
|
166
|
+
- name: Upload sdist
|
|
167
|
+
uses: actions/upload-artifact@v6
|
|
168
|
+
with:
|
|
169
|
+
name: wheels-sdist
|
|
170
|
+
path: dist
|
|
@@ -0,0 +1,50 @@
|
|
|
1
|
+
# Started from `maturin generate-ci github`; maintained by hand.
|
|
2
|
+
name: CI
|
|
3
|
+
|
|
4
|
+
on:
|
|
5
|
+
push:
|
|
6
|
+
branches:
|
|
7
|
+
- main
|
|
8
|
+
- master
|
|
9
|
+
tags:
|
|
10
|
+
- 'v*'
|
|
11
|
+
pull_request:
|
|
12
|
+
workflow_dispatch:
|
|
13
|
+
|
|
14
|
+
permissions:
|
|
15
|
+
contents: read
|
|
16
|
+
|
|
17
|
+
jobs:
|
|
18
|
+
test:
|
|
19
|
+
name: Run Tests
|
|
20
|
+
uses: ./.github/workflows/run-tests.yaml
|
|
21
|
+
|
|
22
|
+
build:
|
|
23
|
+
name: Build Wheels
|
|
24
|
+
uses: ./.github/workflows/build-wheels.yaml
|
|
25
|
+
|
|
26
|
+
release:
|
|
27
|
+
name: Release
|
|
28
|
+
runs-on: ubuntu-latest
|
|
29
|
+
if: ${{ startsWith(github.ref, 'refs/tags/v') }}
|
|
30
|
+
needs: [test, build]
|
|
31
|
+
environment: pypi
|
|
32
|
+
permissions:
|
|
33
|
+
# Used for PyPI trusted publishing and to sign the release artifacts
|
|
34
|
+
id-token: write
|
|
35
|
+
# Used to upload release artifacts
|
|
36
|
+
contents: write
|
|
37
|
+
# Used to generate artifact attestation
|
|
38
|
+
attestations: write
|
|
39
|
+
steps:
|
|
40
|
+
- uses: actions/download-artifact@v7
|
|
41
|
+
- name: Generate artifact attestation
|
|
42
|
+
uses: actions/attest@v4
|
|
43
|
+
with:
|
|
44
|
+
subject-path: 'wheels-*/*'
|
|
45
|
+
- name: Install uv
|
|
46
|
+
if: ${{ startsWith(github.ref, 'refs/tags/v') }}
|
|
47
|
+
uses: astral-sh/setup-uv@v7
|
|
48
|
+
- name: Publish to PyPI
|
|
49
|
+
if: ${{ startsWith(github.ref, 'refs/tags/v') }}
|
|
50
|
+
run: uv publish --trusted-publishing always 'wheels-*/*'
|
|
@@ -0,0 +1,141 @@
|
|
|
1
|
+
name: Run Tests
|
|
2
|
+
|
|
3
|
+
on:
|
|
4
|
+
workflow_call:
|
|
5
|
+
|
|
6
|
+
jobs:
|
|
7
|
+
test:
|
|
8
|
+
name: test (${{ matrix.os }}, ${{ matrix.python }}${{ matrix.python == '3.14' && ', release' || '' }})
|
|
9
|
+
runs-on: ${{ matrix.os }}
|
|
10
|
+
strategy:
|
|
11
|
+
fail-fast: false
|
|
12
|
+
matrix:
|
|
13
|
+
os: [ubuntu-latest, macos-latest, windows-latest]
|
|
14
|
+
python: ["3.11", "3.14", "3.14t"]
|
|
15
|
+
env:
|
|
16
|
+
UV_PYTHON: ${{ matrix.python }}
|
|
17
|
+
UV_PYTHON_PREFERENCE: only-managed
|
|
18
|
+
steps:
|
|
19
|
+
- uses: actions/checkout@v6
|
|
20
|
+
- uses: astral-sh/setup-uv@v7
|
|
21
|
+
- run: uv sync --locked
|
|
22
|
+
- name: Point PyO3 at the test interpreter
|
|
23
|
+
shell: bash
|
|
24
|
+
run: |
|
|
25
|
+
base="$(uv run python -c 'import sys; print(sys.base_prefix)')"
|
|
26
|
+
echo "PYO3_PYTHON=$(uv python find)" >> "$GITHUB_ENV"
|
|
27
|
+
echo "$base" >> "$GITHUB_PATH"
|
|
28
|
+
- run: cargo fmt --check
|
|
29
|
+
- run: cargo clippy --all-targets -- -D warnings
|
|
30
|
+
- run: cargo clippy --all-targets --features test-backend -- -D warnings
|
|
31
|
+
- name: cargo test
|
|
32
|
+
shell: bash
|
|
33
|
+
run: |
|
|
34
|
+
base="$(uv run python -c 'import sys; print(sys.base_prefix)')"
|
|
35
|
+
LD_LIBRARY_PATH="$base/lib" DYLD_LIBRARY_PATH="$base/lib" cargo test --features test-backend
|
|
36
|
+
- run: uv run maturin develop --uv --features test-backend ${{ matrix.python == '3.14' && '--release' || '' }}
|
|
37
|
+
- name: Virtual port pair (Linux)
|
|
38
|
+
if: runner.os == 'Linux'
|
|
39
|
+
run: |
|
|
40
|
+
sudo apt-get update
|
|
41
|
+
sudo apt-get install -y socat
|
|
42
|
+
# socat exits when a slave is closed, so restart it to keep both links alive between tests.
|
|
43
|
+
nohup sh -c 'while true; do socat pty,raw,echo=0,link=/tmp/ttyA pty,raw,echo=0,link=/tmp/ttyB; done' > socat.log 2>&1 &
|
|
44
|
+
for _ in $(seq 20); do
|
|
45
|
+
[ -e /tmp/ttyA ] && [ -e /tmp/ttyB ] && break
|
|
46
|
+
sleep 0.5
|
|
47
|
+
done
|
|
48
|
+
test -e /tmp/ttyA && test -e /tmp/ttyB
|
|
49
|
+
echo "OXISERIAL_PORT_A=/tmp/ttyA" >> "$GITHUB_ENV"
|
|
50
|
+
echo "OXISERIAL_PORT_B=/tmp/ttyB" >> "$GITHUB_ENV"
|
|
51
|
+
- name: Download com0com
|
|
52
|
+
id: com0com-download
|
|
53
|
+
if: runner.os == 'Windows'
|
|
54
|
+
continue-on-error: true
|
|
55
|
+
shell: pwsh
|
|
56
|
+
run: |
|
|
57
|
+
$ErrorActionPreference = 'Stop'
|
|
58
|
+
$dir = Join-Path $env:RUNNER_TEMP "com0com"
|
|
59
|
+
Invoke-WebRequest -UserAgent "oxiserial-ci" -OutFile "$dir.zip" `
|
|
60
|
+
-Uri "https://sourceforge.net/projects/com0com/files/com0com/2.2.2.0/com0com-2.2.2.0-x64-fre-signed.zip/download"
|
|
61
|
+
- name: Extract com0com
|
|
62
|
+
id: com0com-extract
|
|
63
|
+
if: runner.os == 'Windows' && steps.com0com-download.outcome == 'success'
|
|
64
|
+
continue-on-error: true
|
|
65
|
+
shell: pwsh
|
|
66
|
+
run: |
|
|
67
|
+
$ErrorActionPreference = 'Stop'
|
|
68
|
+
$dir = Join-Path $env:RUNNER_TEMP "com0com"
|
|
69
|
+
Expand-Archive "$dir.zip" $dir
|
|
70
|
+
$setup = Get-ChildItem $dir -Recurse -Filter setup.exe | Select-Object -First 1
|
|
71
|
+
if (-not $setup) { throw "setup.exe not found in $dir" }
|
|
72
|
+
7z x -y "-o$dir\driver" $setup.FullName
|
|
73
|
+
if ($LASTEXITCODE -ne 0) { throw "7z failed with exit code $LASTEXITCODE" }
|
|
74
|
+
foreach ($f in "com0com.inf", "com0com.cat", "setupc.exe") {
|
|
75
|
+
if (-not (Test-Path "$dir\driver\$f")) { throw "$f missing from the extracted driver" }
|
|
76
|
+
}
|
|
77
|
+
"COM0COM_DIR=$dir\driver" >> $env:GITHUB_ENV
|
|
78
|
+
- name: Trust the com0com signer
|
|
79
|
+
id: com0com-trust
|
|
80
|
+
if: runner.os == 'Windows' && steps.com0com-extract.outcome == 'success'
|
|
81
|
+
continue-on-error: true
|
|
82
|
+
shell: pwsh
|
|
83
|
+
run: |
|
|
84
|
+
$ErrorActionPreference = 'Stop'
|
|
85
|
+
# A silent driver install needs the publisher certificate trusted first; the driver catalog, not setup.exe, carries the signature.
|
|
86
|
+
$sig = Get-AuthenticodeSignature (Join-Path $env:COM0COM_DIR 'com0com.cat')
|
|
87
|
+
if ($sig.Status -ne 'Valid' -or -not $sig.SignerCertificate) { throw "com0com.cat signature is $($sig.Status)" }
|
|
88
|
+
$store = New-Object System.Security.Cryptography.X509Certificates.X509Store("TrustedPublisher", "LocalMachine")
|
|
89
|
+
$store.Open("ReadWrite")
|
|
90
|
+
$store.Add($sig.SignerCertificate)
|
|
91
|
+
$store.Close()
|
|
92
|
+
- name: Create the port pair
|
|
93
|
+
id: com0com-pair
|
|
94
|
+
if: runner.os == 'Windows' && steps.com0com-trust.outcome == 'success'
|
|
95
|
+
continue-on-error: true
|
|
96
|
+
shell: pwsh
|
|
97
|
+
env:
|
|
98
|
+
PORT_A: COM90
|
|
99
|
+
PORT_B: COM91
|
|
100
|
+
run: |
|
|
101
|
+
$ErrorActionPreference = 'Stop'
|
|
102
|
+
# setupc.exe installs the driver from the .inf in its current directory.
|
|
103
|
+
Push-Location $env:COM0COM_DIR
|
|
104
|
+
try {
|
|
105
|
+
.\setupc.exe --silent install PortName=$env:PORT_A PortName=$env:PORT_B
|
|
106
|
+
if ($LASTEXITCODE -ne 0) { throw "setupc install failed with exit code $LASTEXITCODE" }
|
|
107
|
+
} finally {
|
|
108
|
+
Pop-Location
|
|
109
|
+
}
|
|
110
|
+
- name: Check the ports exist
|
|
111
|
+
id: com0com-check
|
|
112
|
+
if: runner.os == 'Windows' && steps.com0com-pair.outcome == 'success'
|
|
113
|
+
continue-on-error: true
|
|
114
|
+
shell: pwsh
|
|
115
|
+
env:
|
|
116
|
+
PORT_A: COM90
|
|
117
|
+
PORT_B: COM91
|
|
118
|
+
run: |
|
|
119
|
+
$ErrorActionPreference = 'Stop'
|
|
120
|
+
$names = [System.IO.Ports.SerialPort]::GetPortNames()
|
|
121
|
+
Write-Host "Ports: $($names -join ', ')"
|
|
122
|
+
foreach ($p in $env:PORT_A, $env:PORT_B) {
|
|
123
|
+
if ($names -notcontains $p) { throw "Port $p was not created" }
|
|
124
|
+
}
|
|
125
|
+
- name: Export the ports
|
|
126
|
+
id: com0com-export
|
|
127
|
+
if: runner.os == 'Windows' && steps.com0com-check.outcome == 'success'
|
|
128
|
+
continue-on-error: true
|
|
129
|
+
shell: pwsh
|
|
130
|
+
env:
|
|
131
|
+
PORT_A: COM90
|
|
132
|
+
PORT_B: COM91
|
|
133
|
+
run: |
|
|
134
|
+
$ErrorActionPreference = 'Stop'
|
|
135
|
+
"OXISERIAL_PORT_A=$env:PORT_A" >> $env:GITHUB_ENV
|
|
136
|
+
"OXISERIAL_PORT_B=$env:PORT_B" >> $env:GITHUB_ENV
|
|
137
|
+
- run: uv run pytest -v
|
|
138
|
+
- run: uv run mypy
|
|
139
|
+
- run: uv run python -m mypy.stubtest oxiserial
|
|
140
|
+
- run: uv run ruff check python tests
|
|
141
|
+
- run: uv run ruff format --check python tests
|
|
@@ -0,0 +1,80 @@
|
|
|
1
|
+
/target
|
|
2
|
+
|
|
3
|
+
# Byte-compiled / optimized / DLL files
|
|
4
|
+
__pycache__/
|
|
5
|
+
.pytest_cache/
|
|
6
|
+
*.py[cod]
|
|
7
|
+
|
|
8
|
+
# C extensions
|
|
9
|
+
*.so
|
|
10
|
+
|
|
11
|
+
# Distribution / packaging
|
|
12
|
+
.Python
|
|
13
|
+
.venv/
|
|
14
|
+
env/
|
|
15
|
+
bin/
|
|
16
|
+
build/
|
|
17
|
+
develop-eggs/
|
|
18
|
+
dist/
|
|
19
|
+
eggs/
|
|
20
|
+
lib/
|
|
21
|
+
lib64/
|
|
22
|
+
parts/
|
|
23
|
+
sdist/
|
|
24
|
+
var/
|
|
25
|
+
include/
|
|
26
|
+
man/
|
|
27
|
+
venv/
|
|
28
|
+
*.egg-info/
|
|
29
|
+
.installed.cfg
|
|
30
|
+
*.egg
|
|
31
|
+
|
|
32
|
+
# Installer logs
|
|
33
|
+
pip-log.txt
|
|
34
|
+
pip-delete-this-directory.txt
|
|
35
|
+
pip-selfcheck.json
|
|
36
|
+
|
|
37
|
+
# Unit test / coverage reports
|
|
38
|
+
htmlcov/
|
|
39
|
+
.tox/
|
|
40
|
+
.coverage
|
|
41
|
+
.cache
|
|
42
|
+
nosetests.xml
|
|
43
|
+
coverage.xml
|
|
44
|
+
|
|
45
|
+
# Translations
|
|
46
|
+
*.mo
|
|
47
|
+
|
|
48
|
+
# Mr Developer
|
|
49
|
+
.mr.developer.cfg
|
|
50
|
+
.project
|
|
51
|
+
.pydevproject
|
|
52
|
+
|
|
53
|
+
# Rope
|
|
54
|
+
.ropeproject
|
|
55
|
+
|
|
56
|
+
# Django stuff:
|
|
57
|
+
*.log
|
|
58
|
+
*.pot
|
|
59
|
+
|
|
60
|
+
.DS_Store
|
|
61
|
+
|
|
62
|
+
# Sphinx documentation
|
|
63
|
+
docs/_build/
|
|
64
|
+
|
|
65
|
+
# PyCharm
|
|
66
|
+
.idea/
|
|
67
|
+
|
|
68
|
+
# VSCode
|
|
69
|
+
.vscode/
|
|
70
|
+
|
|
71
|
+
# Pyenv
|
|
72
|
+
.python-version
|
|
73
|
+
|
|
74
|
+
# claude
|
|
75
|
+
.claude/settings.local.json
|
|
76
|
+
.claude/plans
|
|
77
|
+
.superpowers/
|
|
78
|
+
.mypy_cache/
|
|
79
|
+
*.pyd
|
|
80
|
+
*.pdb
|
|
@@ -0,0 +1,51 @@
|
|
|
1
|
+
# oxiserial
|
|
2
|
+
|
|
3
|
+
Serial port library for Python, implemented in Rust with PyO3 and built with
|
|
4
|
+
maturin. `import oxiserial as serial` replaces `pyserial` 3.5.
|
|
5
|
+
`oxiserial.aio.Serial` has the same API, but its I/O methods return a future
|
|
6
|
+
that can be waited on (`.wait()`) or awaited.
|
|
7
|
+
|
|
8
|
+
## Layout
|
|
9
|
+
|
|
10
|
+
- `src/`: all runtime code (Rust). The extension module is
|
|
11
|
+
`oxiserial._oxiserial`.
|
|
12
|
+
- `python/oxiserial/`: `.pyi` stubs, `py.typed`, and an `__init__.py` that
|
|
13
|
+
only re-exports `oxiserial._oxiserial`.
|
|
14
|
+
- `.github/workflows/`: `ci.yaml` calls `run-tests.yaml` and
|
|
15
|
+
`build-wheels.yaml`, then publishes. Started from `maturin generate-ci
|
|
16
|
+
github`, now maintained by hand.
|
|
17
|
+
|
|
18
|
+
## Rules
|
|
19
|
+
|
|
20
|
+
- `pyserial` 3.5 is the specification for the public API: names, signatures,
|
|
21
|
+
defaults, exception types and behaviour.
|
|
22
|
+
- Code or text taken from pyserial gets a one-line comment saying so; the
|
|
23
|
+
notice is in `LICENSES/pyserial.txt`.
|
|
24
|
+
- OS access goes through crates (`serialport`, `tokio-serial`, and `nix` or
|
|
25
|
+
`windows-sys` for what those lack). No hand-written FFI.
|
|
26
|
+
- Every item exposed to Python has a matching stub entry; `stubtest` checks
|
|
27
|
+
they agree.
|
|
28
|
+
- Blocking calls release the GIL. Shared state is behind a `Mutex` or
|
|
29
|
+
atomics, since the module supports free-threaded CPython.
|
|
30
|
+
- CPython 3.11 or newer. Wheels are `abi3-py311` plus `cp314t`.
|
|
31
|
+
- Releases are cut by pushing a `vX.Y.Z` tag; CI sets the version from it.
|
|
32
|
+
- Dependencies go through `uv add` and `cargo add`, never by editing
|
|
33
|
+
`pyproject.toml` or `Cargo.toml` by hand.
|
|
34
|
+
|
|
35
|
+
## Commands
|
|
36
|
+
|
|
37
|
+
```sh
|
|
38
|
+
uv sync
|
|
39
|
+
uv run maturin develop --uv --features test-backend
|
|
40
|
+
cargo fmt --check
|
|
41
|
+
cargo clippy --all-targets --features test-backend -- -D warnings
|
|
42
|
+
cargo test --features test-backend
|
|
43
|
+
uv run pytest
|
|
44
|
+
uv run ruff check python tests
|
|
45
|
+
uv run ruff format --check python tests
|
|
46
|
+
uv run mypy
|
|
47
|
+
uv run python -m mypy.stubtest oxiserial
|
|
48
|
+
```
|
|
49
|
+
|
|
50
|
+
Run all of them before reporting a change as done. Real-port tests need a
|
|
51
|
+
connected pair: `uv run pytest --port-a <A> --port-b <B>`.
|