Skip to content

Commit fca16e0

Browse files
authored
chore/pypi Publish to PyPI (#5)
* Restructure project * Add pypi publish workflow * Add version check workflow * Fix version check
1 parent b732f2a commit fca16e0

9 files changed

Lines changed: 565 additions & 428 deletions

File tree

.github/workflows/publish.yml

Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,29 @@
1+
name: Publish to PyPI
2+
3+
on:
4+
push:
5+
tags:
6+
- "v*"
7+
8+
jobs:
9+
build-n-publish:
10+
name: Build and publish Python distro to PyPI
11+
runs-on: ubuntu-latest
12+
environment:
13+
name: pypi
14+
url: https://pypi.org/p/sensirion-sps30
15+
permissions:
16+
id-token: write
17+
contents: read
18+
steps:
19+
- uses: actions/checkout@v4
20+
- name: Install uv
21+
uses: astral-sh/setup-uv@v5
22+
with:
23+
enable-cache: true
24+
- name: Set up Python
25+
run: uv python install
26+
- name: Build package
27+
run: uv build
28+
- name: Publish package
29+
run: uv publish
Lines changed: 39 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,39 @@
1+
name: Version Check
2+
3+
on:
4+
pull_request:
5+
branches:
6+
- main
7+
paths:
8+
- "pyproject.toml"
9+
10+
jobs:
11+
check-version:
12+
runs-on: ubuntu-latest
13+
steps:
14+
- uses: actions/checkout@v4
15+
16+
- name: Install uv
17+
uses: astral-sh/setup-uv@v5
18+
19+
- name: Get Local Version
20+
id: local_version
21+
run: |
22+
# Extracts version from pyproject.toml using uv
23+
VERSION=$(grep -m 1 '^version = ' pyproject.toml | cut -d '"' -f 2)
24+
echo "version=$VERSION" >> $GITHUB_OUTPUT
25+
echo "Detected local version: $VERSION"
26+
27+
- name: Check PyPI Version
28+
id: pypi_check
29+
run: |
30+
PACKAGE_NAME=$(grep -m 1 "name =" pyproject.toml | cut -d '"' -f 2)
31+
# Query PyPI API for the latest version
32+
LATEST_PYPI=$(curl -s https://pypi.org/pypi/$PACKAGE_NAME/json | jq -r '.info.version' || echo "0.0.0")
33+
34+
if [ "${{ steps.local_version.outputs.version }}" == "$LATEST_PYPI" ]; then
35+
echo "Version ${{ steps.local_version.outputs.version }} already exists on PyPI!"
36+
exit 1
37+
else
38+
echo "Version bump detected: $LATEST_PYPI -> ${{ steps.local_version.outputs.version }}"
39+
fi

LICENSE

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
MIT License
22

3-
Copyright (c) 2021 Dave
3+
Copyright (c) 2026 David
44

55
Permission is hereby granted, free of charge, to any person obtaining a copy
66
of this software and associated documentation files (the "Software"), to deal

example.py

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,18 +1,19 @@
1-
import sys
21
import json
2+
import sys
33
from time import sleep
4-
from sps30 import SPS30
54

5+
from sps30 import SPS30
66

77
if __name__ == "__main__":
88
pm_sensor = SPS30()
99
print(f"Firmware version: {pm_sensor.firmware_version()}")
1010
print(f"Product type: {pm_sensor.product_type()}")
1111
print(f"Serial number: {pm_sensor.serial_number()}")
1212
print(f"Status register: {pm_sensor.read_status_register()}")
13+
print(f"Auto cleaning interval: {pm_sensor.read_auto_cleaning_interval()}s")
1314
print(
14-
f"Auto cleaning interval: {pm_sensor.read_auto_cleaning_interval()}s")
15-
print(f"Set auto cleaning interval: {pm_sensor.write_auto_cleaning_interval_days(2)}s")
15+
f"Set auto cleaning interval: {pm_sensor.write_auto_cleaning_interval_days(2)}s"
16+
)
1617
pm_sensor.start_measurement()
1718

1819
while True:

pyproject.toml

Lines changed: 42 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,42 @@
1+
[project]
2+
name = "sensirion-sps30"
3+
version = "0.1.0"
4+
description = "Python-based driver for Sensirion SPS30 particulate matter sensor over I2C"
5+
readme = "README.md"
6+
requires-python = ">=3.10"
7+
license = { file = "LICENSE" }
8+
authors = [
9+
{ name = "David", email = "imdavidsu@gmail.com" }
10+
]
11+
dependencies = []
12+
13+
[tool.hatch.build.targets.wheel]
14+
packages = ["src/sps30"]
15+
16+
[dependency-groups]
17+
dev = [
18+
"ruff>=0.15.7",
19+
]
20+
21+
[tool.ruff]
22+
line-length = 88
23+
target-version = "py310"
24+
25+
[tool.ruff.lint]
26+
select = [
27+
"E", # pycodestyle errors
28+
"W", # pycodestyle warnings
29+
"F", # pyflakes
30+
"I", # isort
31+
"C4", # flake8-comprehensions
32+
"B", # flake8-bugbear
33+
"UP", # pyupgrade
34+
]
35+
ignore = []
36+
37+
[build-system]
38+
requires = ["hatchling"]
39+
build-backend = "hatchling.build"
40+
41+
[tool.pyright]
42+
extraPaths = ["src"]

src/sps30/__init__.py

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
from .sps30 import SPS30
2+
3+
__all__ = ["SPS30"]
Lines changed: 24 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -1,26 +1,24 @@
1-
import io
2-
from fcntl import ioctl
3-
4-
I2C_SLAVE = 0x0703
5-
6-
7-
class I2C:
8-
9-
def __init__(self, bus: int, address: int):
10-
11-
self.fr = io.open("/dev/i2c-"+str(bus), "rb", buffering=0)
12-
self.fw = io.open("/dev/i2c-"+str(bus), "wb", buffering=0)
13-
14-
# set device address
15-
ioctl(self.fr, I2C_SLAVE, address)
16-
ioctl(self.fw, I2C_SLAVE, address)
17-
18-
def write(self, data: list):
19-
self.fw.write(bytearray(data))
20-
21-
def read(self, nbytes: int) -> list:
22-
return list(self.fr.read(nbytes))
23-
24-
def close(self):
25-
self.fw.close()
26-
self.fr.close()
1+
from fcntl import ioctl
2+
3+
I2C_SLAVE = 0x0703
4+
5+
6+
class I2C:
7+
def __init__(self, bus: int, address: int):
8+
9+
self.fr = open("/dev/i2c-" + str(bus), "rb", buffering=0)
10+
self.fw = open("/dev/i2c-" + str(bus), "wb", buffering=0)
11+
12+
# set device address
13+
ioctl(self.fr, I2C_SLAVE, address)
14+
ioctl(self.fw, I2C_SLAVE, address)
15+
16+
def write(self, data: list):
17+
self.fw.write(bytearray(data))
18+
19+
def read(self, nbytes: int) -> list:
20+
return list(self.fr.read(nbytes))
21+
22+
def close(self):
23+
self.fw.close()
24+
self.fr.close()

0 commit comments

Comments
 (0)