Skip to content

Commit b6c1890

Browse files
authored
Add typechecking (#15)
* Add typechecking * Fix typecheck in CI * Update pysquared version * empty
1 parent 4693e43 commit b6c1890

File tree

8 files changed

+253
-9
lines changed

8 files changed

+253
-9
lines changed

.github/workflows/ci.yaml

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,13 @@ jobs:
1414
- name: Lint
1515
run: |
1616
make fmt
17+
typecheck:
18+
runs-on: ubuntu-latest
19+
steps:
20+
- uses: actions/checkout@v4
21+
- name: Typecheck
22+
run: |
23+
make typecheck
1724
archive:
1825
runs-on: ubuntu-latest
1926
steps:

Makefile

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
PYSQUARED_VERSION ?= v2.0.0-alpha-25w14-3
1+
PYSQUARED_VERSION ?= v2.0.0-alpha-25w17
22
PYSQUARED ?= git+https://github.com/proveskit/pysquared@$(PYSQUARED_VERSION)
33

44
.PHONY: all
@@ -38,6 +38,9 @@ sync-time: uv ## Syncs th time from your computer to the PROVES Kit board
3838
fmt: pre-commit-install ## Lint and format files
3939
$(UVX) pre-commit run --all-files
4040

41+
typecheck: .venv download-libraries ## Run type check
42+
@$(UV) run -m pyright .
43+
4144
BOARD_MOUNT_POINT ?= ""
4245
VERSION ?= $(shell git tag --points-at HEAD --sort=-creatordate < /dev/null | head -n 1)
4346

main.py

Lines changed: 4 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@
1313

1414
import digitalio
1515
import microcontroller
16+
from busio import SPI
1617

1718
try:
1819
from board_definitions import proveskit_rp2040_v4 as board
@@ -42,7 +43,7 @@
4243
rtc = MicrocontrollerManager()
4344

4445
logger: Logger = Logger(
45-
error_counter=Counter(index=register.ERRORCNT, datastore=microcontroller.nvm),
46+
error_counter=Counter(index=register.ERRORCNT),
4647
colorized=False,
4748
)
4849

@@ -66,7 +67,7 @@
6667
config: Config = Config("config.json")
6768

6869
# TODO(nateinaction): fix spi init
69-
spi0 = _spi_init(
70+
spi0: SPI = _spi_init(
7071
logger,
7172
board.SPI0_SCK,
7273
board.SPI0_MOSI,
@@ -76,7 +77,7 @@
7677
radio = RFM9xManager(
7778
logger,
7879
config.radio,
79-
Flag(index=register.FLAG, bit_index=7, datastore=microcontroller.nvm),
80+
Flag(index=register.FLAG, bit_index=7),
8081
spi0,
8182
initialize_pin(logger, board.SPI0_CS0, digitalio.Direction.OUTPUT, True),
8283
initialize_pin(logger, board.RF1_RST, digitalio.Direction.OUTPUT, True),
@@ -153,9 +154,7 @@ def main():
153154

154155
f.listen_loiter()
155156

156-
f.all_face_data()
157157
watchdog.pet()
158-
f.send_face()
159158

160159
f.listen_loiter()
161160

pyproject.toml

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@ dependencies = [
99
"circuitpython-stubs==9.2.5",
1010
"coverage==7.6.10",
1111
"pre-commit==4.0.1",
12+
"pyright[nodejs]==1.1.399",
1213
"pytest==8.3.2",
1314
]
1415

@@ -49,3 +50,16 @@ directory = ".coverage-reports/html"
4950

5051
[tool.coverage.xml]
5152
output = ".coverage-reports/coverage.xml"
53+
54+
[tool.pyright]
55+
include = ["main.py", "boot.py", "repl.py", "safemode.py"]
56+
exclude = [
57+
"**/__pycache__",
58+
".venv",
59+
".git",
60+
"artifacts",
61+
"lib",
62+
"typings",
63+
]
64+
stubPath = "./typings"
65+
reportMissingModuleSource = false

repl.py

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,13 +1,11 @@
1-
import microcontroller
2-
31
import lib.pysquared.nvm.register as register
42
from lib.pysquared.config.config import Config
53
from lib.pysquared.logger import Logger
64
from lib.pysquared.nvm.counter import Counter
75
from lib.pysquared.satellite import Satellite
86

97
logger: Logger = Logger(
10-
error_counter=Counter(index=register.ERRORCNT, datastore=microcontroller.nvm),
8+
error_counter=Counter(index=register.ERRORCNT),
119
colorized=False,
1210
)
1311
config: Config = Config("config.json")

typings/board.pyi

Lines changed: 71 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,71 @@
1+
# SPDX-FileCopyrightText: 2024 Justin Myers
2+
#
3+
# SPDX-License-Identifier: MIT
4+
"""
5+
Board stub for PROVES Kit v4
6+
- port: raspberrypi
7+
- board_id: proveskit_rp2040_v4
8+
- NVM size: 4096
9+
- Included modules: _asyncio, _bleio, _pixelmap, adafruit_bus_device, adafruit_pixelbuf, aesio, alarm, analogbufio, analogio, array, atexit, audiobusio, audiocore, audiomixer, audiomp3, audiopwmio, binascii, bitbangio, bitmapfilter, bitmaptools, bitops, board, builtins, builtins.pow3, busdisplay, busio, busio.SPI, busio.UART, codeop, collections, countio, digitalio, displayio, epaperdisplay, errno, floppyio, fontio, fourwire, framebufferio, getpass, gifio, hashlib, i2cdisplaybus, i2ctarget, imagecapture, io, jpegio, json, keypad, keypad.KeyMatrix, keypad.Keys, keypad.ShiftRegisterKeys, keypad_demux, keypad_demux.DemuxKeyMatrix, locale, math, memorymap, microcontroller, msgpack, neopixel_write, nvm, onewireio, os, os.getenv, paralleldisplaybus, pulseio, pwmio, qrio, rainbowio, random, re, rgbmatrix, rotaryio, rp2pio, rtc, sdcardio, select, sharpdisplay, storage, struct, supervisor, synthio, sys, terminalio, tilepalettemapper, time, touchio, traceback, ulab, usb, usb_cdc, usb_hid, usb_host, usb_midi, usb_video, vectorio, warnings, watchdog, zlib
10+
- Frozen libraries:
11+
---
12+
proveskit: Borrowed from circuitpython-stubs https://pypi.org/project/circuitpython-stubs/#files board definitions
13+
"""
14+
15+
# Imports
16+
import busio
17+
import microcontroller
18+
19+
# Board Info:
20+
board_id: str
21+
22+
# Pins:
23+
SPI0_CS1: microcontroller.Pin # GPIO26
24+
NEO_PWR: microcontroller.Pin # GPIO27
25+
SPI0_CS2: microcontroller.Pin # GPIO28
26+
D0: microcontroller.Pin # GPIO29
27+
D8: microcontroller.Pin # GPIO18
28+
D9: microcontroller.Pin # GPIO19
29+
D6: microcontroller.Pin # GPIO16
30+
TX: microcontroller.Pin # GPIO0
31+
RX: microcontroller.Pin # GPIO1
32+
I2C1_SDA: microcontroller.Pin # GPIO2
33+
I2C1_SCL: microcontroller.Pin # GPIO3
34+
I2C0_SDA: microcontroller.Pin # GPIO4
35+
I2C0_SCL: microcontroller.Pin # GPIO5
36+
PC: microcontroller.Pin # GPIO6
37+
VS: microcontroller.Pin # GPIO7
38+
SPI0_MISO: microcontroller.Pin # GPIO8
39+
SPI0_CS0: microcontroller.Pin # GPIO9
40+
SPI0_SCK: microcontroller.Pin # GPIO10
41+
SPI0_MOSI: microcontroller.Pin # GPIO11
42+
D2: microcontroller.Pin # GPIO12
43+
D3: microcontroller.Pin # GPIO13
44+
D4: microcontroller.Pin # GPIO14
45+
D5: microcontroller.Pin # GPIO15
46+
RF1_RST: microcontroller.Pin # GPIO20
47+
WDT_WDI: microcontroller.Pin # GPIO21
48+
RF1_IO4: microcontroller.Pin # GPIO22
49+
RF1_IO0: microcontroller.Pin # GPIO23
50+
NEOPIX: microcontroller.Pin # GPIO24
51+
HS: microcontroller.Pin # GPIO25
52+
D7: microcontroller.Pin # GPIO17
53+
54+
# Members:
55+
def I2C() -> busio.I2C:
56+
"""Returns the `busio.I2C` object for the board's designated I2C bus(es).
57+
The object created is a singleton, and uses the default parameter values for `busio.I2C`.
58+
"""
59+
60+
def SPI() -> busio.SPI:
61+
"""Returns the `busio.SPI` object for the board's designated SPI bus(es).
62+
The object created is a singleton, and uses the default parameter values for `busio.SPI`.
63+
"""
64+
65+
def UART() -> busio.UART:
66+
"""Returns the `busio.UART` object for the board's designated UART bus(es).
67+
The object created is a singleton, and uses the default parameter values for `busio.UART`.
68+
"""
69+
70+
# Unmapped:
71+
# none

typings/gc.pyi

Lines changed: 116 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,116 @@
1+
"""
2+
Control the garbage collector.
3+
4+
MicroPython module: https://docs.micropython.org/en/v1.25.0/library/gc.html
5+
6+
CPython module: :mod:`python:gc` https://docs.python.org/3/library/gc.html .
7+
8+
---
9+
Module: 'gc' on micropython-v1.25.0-rp2-RPI_PICO
10+
---
11+
proveskit: Borrowed from https://github.com/Josverl/micropython-stubs
12+
https://pypi.org/project/micropython-rp2-stubs/#files
13+
"""
14+
15+
# MCU: {'build': '', 'ver': '1.25.0', 'version': '1.25.0', 'port': 'rp2', 'board': 'RPI_PICO', 'mpy': 'v6.3', 'family': 'micropython', 'cpu': 'RP2040', 'arch': 'armv6m'}
16+
# Stubber: v1.24.0
17+
from __future__ import annotations
18+
19+
from typing import overload
20+
21+
from _typeshed import Incomplete
22+
23+
def mem_alloc() -> int:
24+
"""
25+
Return the number of bytes of heap RAM that are allocated by Python code.
26+
27+
Admonition:Difference to CPython
28+
:class: attention
29+
30+
This function is MicroPython extension.
31+
"""
32+
...
33+
34+
def isenabled(*args, **kwargs) -> Incomplete: ...
35+
def mem_free() -> int:
36+
"""
37+
Return the number of bytes of heap RAM that is available for Python
38+
code to allocate, or -1 if this amount is not known.
39+
40+
Admonition:Difference to CPython
41+
:class: attention
42+
43+
This function is MicroPython extension.
44+
"""
45+
...
46+
47+
@overload
48+
def threshold() -> int:
49+
"""
50+
Set or query the additional GC allocation threshold. Normally, a collection
51+
is triggered only when a new allocation cannot be satisfied, i.e. on an
52+
out-of-memory (OOM) condition. If this function is called, in addition to
53+
OOM, a collection will be triggered each time after *amount* bytes have been
54+
allocated (in total, since the previous time such an amount of bytes
55+
have been allocated). *amount* is usually specified as less than the
56+
full heap size, with the intention to trigger a collection earlier than when the
57+
heap becomes exhausted, and in the hope that an early collection will prevent
58+
excessive memory fragmentation. This is a heuristic measure, the effect
59+
of which will vary from application to application, as well as
60+
the optimal value of the *amount* parameter.
61+
62+
Calling the function without argument will return the current value of
63+
the threshold. A value of -1 means a disabled allocation threshold.
64+
65+
Admonition:Difference to CPython
66+
:class: attention
67+
68+
This function is a MicroPython extension. CPython has a similar
69+
function - ``set_threshold()``, but due to different GC
70+
implementations, its signature and semantics are different.
71+
"""
72+
73+
@overload
74+
def threshold(amount: int) -> None:
75+
"""
76+
Set or query the additional GC allocation threshold. Normally, a collection
77+
is triggered only when a new allocation cannot be satisfied, i.e. on an
78+
out-of-memory (OOM) condition. If this function is called, in addition to
79+
OOM, a collection will be triggered each time after *amount* bytes have been
80+
allocated (in total, since the previous time such an amount of bytes
81+
have been allocated). *amount* is usually specified as less than the
82+
full heap size, with the intention to trigger a collection earlier than when the
83+
heap becomes exhausted, and in the hope that an early collection will prevent
84+
excessive memory fragmentation. This is a heuristic measure, the effect
85+
of which will vary from application to application, as well as
86+
the optimal value of the *amount* parameter.
87+
88+
Calling the function without argument will return the current value of
89+
the threshold. A value of -1 means a disabled allocation threshold.
90+
91+
Admonition:Difference to CPython
92+
:class: attention
93+
94+
This function is a MicroPython extension. CPython has a similar
95+
function - ``set_threshold()``, but due to different GC
96+
implementations, its signature and semantics are different.
97+
"""
98+
99+
def collect() -> None:
100+
"""
101+
Run a garbage collection.
102+
"""
103+
...
104+
105+
def enable() -> None:
106+
"""
107+
Enable automatic garbage collection.
108+
"""
109+
...
110+
111+
def disable() -> None:
112+
"""
113+
Disable automatic garbage collection. Heap memory can still be allocated,
114+
and garbage collection can still be initiated manually using :meth:`gc.collect`.
115+
"""
116+
...

uv.lock

Lines changed: 36 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

0 commit comments

Comments
 (0)