Developing the package¶
For changing the ents package itself. If you only want to use it, see
Using the package.
Setup¶
From the repository root:
cd python
python -m venv .venv
source .venv/bin/activate # Windows: .venv\Scripts\activate
pip install -e .[dev]
Editable install, so changes take effect without reinstalling.
Running things locally¶
All three scripts honour CI=true, which makes them report problems instead of
fixing them, exactly as CI runs them.
./test.sh # python -m unittest
./lint.sh # ruff check --fix (CI=true: check only)
./format.sh # ruff format (CI=true: --check only)
A single test file, while iterating:
python -m unittest tests.test_sensor -v
Important
Match CI’s ruff version. pip install -e .[dev] is unpinned, so a newer ruff
can report findings CI does not, or miss ones it does. If ./lint.sh passes
locally and CI disagrees, check the version in the CI log first.
Building these docs¶
cd python/docs
./build.sh # ./build.sh --open to open it afterwards
Output in docs/build/html/index.html. Requires the docs extra:
pip install -e .[docs]
Pages are Markdown via MyST. The API reference is generated from docstrings, so document the code, not the reference page.
Docstrings are Google style, which is what sphinx.ext.napoleon is
configured for:
def example(cell, start):
"""One line summary.
Longer explanation if it earns its place.
Args:
cell: What it is.
start: What it is.
Returns:
What comes back.
Raises:
ValueError: When.
"""
Adding a SensorType¶
Adding a value to the SensorType enum takes three steps, and skipping the
third breaks data collection in a way nothing warns you about.
Add it to
proto/sensor.proto.Regenerate the bindings:
cd proto make # or: make c / make python
This writes both the C sources under
embedded/libents/andsensor_pb2.pyhere. Commit the generated files; they are checked in.Add an entry to
SENSOR_DATAinsrc/ents/proto/sensor.py.
Step 3 is not optional. get_sensor_data() looks the type up with a bare dict
access, and DirtViz calls parse_sensor_measurement() from this package on
every uplink. A missing entry raises KeyError, which the backend turns into
an HTTP 400 for the entire batch — discarding every real measurement that
happened to be uploaded alongside it, on every upload, with nothing on the node
to indicate anything is wrong.
Nothing currently fails the test suite when an entry is missing, so this is worth checking by hand until something does.
The two names matter downstream: DirtViz files a measurement under the enum
name (POWER_VOLTAGE) with the name field as its measurement
(Voltage), and that pair is what sensor_data() queries by.
Regenerating protobuf without a system protoc¶
The proto/Makefile expects protoc and nanopb_generator on PATH. If you
only need the python side:
pip install grpcio-tools
python -m grpc_tools.protoc -I proto --python_out=proto/build proto/sensor.proto
cp proto/build/sensor_pb2.py python/src/ents/proto/
Check the generated header comment says a protobuf version compatible with the
pin in pyproject.toml; generated code newer than the runtime fails at import.
Releasing¶
pyproject.toml holds the version. Bumping it matters beyond PyPI: DirtViz
imports parse_sensor_measurement from this package, so a decoding change only
reaches production once a release ships and the backend picks it up.