A high-performance, dark-mode SCADA UI widget library for PyQt6.
Project description
SCADA UI Kit
A robust, enterprise-grade industrial UI widget library for PyQt6, engineered for
performance, deep customisation, and a smooth developer experience. The codebase is
written to Fluent Python (2e) idioms: rich data-model methods, property-based APIs,
deque-backed buffers, IntEnum state codes, Qt-signal observers, and fully typed
public interfaces (PEP 561).
Features
ScadaRadialGauge- dark-mode radial gauge with a configurable alert threshold that turns the needle red above 80% of range. Assign to.valueand the widget repaints itself.ScadaStripChart- real-time scrolling telemetry chart backed by a fixed-lengthcollections.dequefor O(1) appends and automatic eviction of the oldest sample. Iterable and subscriptable like a normal sequence.ScadaIndicator+ScadaIndicatorMatrix- multi-state LED indicators laid out in a grid. The matrix implements the full mapping protocol, so you can writematrix["COOLANT"] = IndicatorState.RUNNING, iterate withfor name in matrix, and check membership with"COOLANT" in matrix.ScadaToggle- heavy-duty actuator switch that emitstoggled(bool)so you can wire control inputs straight to your indicator matrix or business logic.IndicatorStateenum -OFFLINE,RUNNING,WARNING,FAULT. It's anIntEnum, so raw integers still work for back-compat.- Typed - every public symbol ships with type hints and a PEP 561
py.typedmarker, somypyandpyrightpick up the annotations out of the box.
Installation
From the project root:
pip install .
Or, for local development with live code reloads:
pip install -e .
PyQt6 is pulled in automatically as a dependency.
Quick Start
import sys
from PyQt6.QtWidgets import QApplication
from scada_ui_kit import ScadaRadialGauge
app = QApplication(sys.argv)
gauge = ScadaRadialGauge(title="REACTOR PRESSURE", unit="PSI", min_val=0, max_val=150)
gauge.value = 87 # property assignment - triggers the repaint automatically
gauge.show()
sys.exit(app.exec())
Mapping-style status updates
from scada_ui_kit import IndicatorState, ScadaIndicatorMatrix
matrix = ScadaIndicatorMatrix(columns=2)
for name in ("COOLANT", "CORE TEMP", "CONTAINMENT", "VENTILATION"):
matrix.add_indicator(name)
matrix["COOLANT"] = IndicatorState.RUNNING
matrix["VENTILATION"] = IndicatorState.WARNING
assert "COOLANT" in matrix
for system in matrix: # __iter__ yields indicator names
print(system, matrix[system].state) # __getitem__ returns the widget
Toggle with observer wiring
from scada_ui_kit import IndicatorState, ScadaToggle
pump = ScadaToggle()
pump.toggled.connect(
lambda on: matrix.__setitem__(
"COOLANT",
IndicatorState.RUNNING if on else IndicatorState.OFFLINE,
)
)
Running the demos
The repository ships with five runnable scripts at the project root. Once the package
is installed (pip install -e .):
python main_dashboard.py # unified dashboard with all widgets and a live feed
python scada_gauge.py # slider-driven gauge demo
python scada_chart.py # sine-wave + noise strip chart
python scada_matrix.py # indicator matrix showcase
python scada_toggle.py # toggle wired to a live status label
Requirements
- Python 3.10+
- PyQt6 6.0+
Building distribution artifacts
The repo ships a small helper that produces an sdist and a wheel in ./dist/
and validates them with twine check before any upload.
pip install -e .[build] # installs the `build` + `twine` tools locally
python build_package.py # clean -> build -> twine check -> summary
Useful flags:
python build_package.py --clean-only # just wipe dist/ and build/
python build_package.py --no-clean # keep previous artifacts
python build_package.py --no-check # skip the twine validation pass
A successful run prints something like:
[build] artifacts ready in ./dist/:
scada_ui_kit-0.1.0-py3-none-any.whl 12.3 KB
scada_ui_kit-0.1.0.tar.gz 10.1 KB
The wheel is a single, self-contained file you can distribute to users - they
install it with pip install scada_ui_kit-0.1.0-py3-none-any.whl.
Bumping the version
The package version lives in one place: __version__ in
scada_ui_kit/__init__.py. pyproject.toml resolves it dynamically at build
time via setuptools' attr directive, so drift is impossible by construction.
python bump_version.py patch # 0.1.0 -> 0.1.1 (bug fix)
python bump_version.py minor # 0.1.0 -> 0.2.0 (back-compatible feature)
python bump_version.py major # 0.1.0 -> 1.0.0 (breaking change)
python bump_version.py 2.7.3 # explicit SemVer set
python bump_version.py patch -n # dry-run: print the new version and exit
Git automation
python bump_version.py patch -c # write + 'git add' + 'git commit'
python bump_version.py patch -c -t # also create an annotated 'vX.Y.Z' tag
Safety checks that run before anything is written:
- If
--commitor--tagis requested,git rev-parse --is-inside-work-treeverifies we're actually in a repo. - If
--tagis requested,git tag --list vX.Y.Zmust be empty (no clobber). - The commit is scoped with
git commit -- scada_ui_kit/__init__.pyso any unrelated already-staged changes don't get swept into the release commit.
After a successful --commit -t, push with:
git push && git push origin vX.Y.Z
Typical release flow
python bump_version.py patch -c -t # write, commit, tag
python build_package.py # sdist + wheel + twine check
python publish.py # TestPyPI (safe default)
python publish.py --production # real PyPI, with y/N prompt
git push && git push origin vX.Y.Z # share the release commit/tag
Publishing to PyPI / TestPyPI
Once the artifacts in dist/ are validated, publish.py uploads them with
sensible safety defaults:
python publish.py # uploads to TestPyPI (safe default)
python publish.py --production # uploads to real PyPI; asks for 'yes'
python publish.py --production -y # non-interactive production upload (CI)
Authentication is delegated to twine, so any of the standard mechanisms work:
TWINE_USERNAME/TWINE_PASSWORDenvironment variables (recommended for CI; setTWINE_USERNAME=__token__andTWINE_PASSWORD=<your PyPI API token>).- A
~/.pypircfile with[pypi]and[testpypi]sections. - The system keyring, if configured.
Safety features baked into the script:
twine checkruns before any upload so malformed metadata is caught locally.- Production uploads require both
--productionand an explicityesconfirmation (or--yesfor automation). - Non-interactive environments (no TTY) without
--yesare refused outright for production, preventing accidents in cron jobs and CI triggers.
License
MIT
Project details
Release history Release notifications | RSS feed
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distribution
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
File details
Details for the file scada_ui_kit-0.1.1.tar.gz.
File metadata
- Download URL: scada_ui_kit-0.1.1.tar.gz
- Upload date:
- Size: 13.7 kB
- Tags: Source
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/6.2.0 CPython/3.14.4
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
515fcd2300653e5d28119663d2a7479572451e2b30e4a5923064d862545ae9ee
|
|
| MD5 |
60ce1301ba4d481b5b5eb8f86a81635a
|
|
| BLAKE2b-256 |
7ae13b8bda6f4d4c7dec037398ee8cffff6eb9a0bd88bbd2c57f242ff6eb5a69
|
File details
Details for the file scada_ui_kit-0.1.1-py3-none-any.whl.
File metadata
- Download URL: scada_ui_kit-0.1.1-py3-none-any.whl
- Upload date:
- Size: 10.8 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/6.2.0 CPython/3.14.4
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
d755c3f91a4beebcb9daa7d49cd708f73a631f84f9877cc899600e7f75b5d674
|
|
| MD5 |
808a5b0002a104b20f4d2e85dc52d7ec
|
|
| BLAKE2b-256 |
1ece28f84e8f7adaaaf15a5fbf7347a7ffcc3016510319c8a6455d6fcdb218bd
|