diff --git a/.codespellrc b/.codespellrc index d3822d5..c3ecea3 100644 --- a/.codespellrc +++ b/.codespellrc @@ -1,2 +1,2 @@ [codespell] -skip = ./.git/*,Pipfile.lock +skip = ./.git/*,uv.lock,.venv/* diff --git a/.github/ISSUE_TEMPLATE/feature_request.md b/.github/ISSUE_TEMPLATE/feature_request.md index f9acdb3..135064b 100644 --- a/.github/ISSUE_TEMPLATE/feature_request.md +++ b/.github/ISSUE_TEMPLATE/feature_request.md @@ -2,9 +2,8 @@ name: Feature request about: Suggest an idea for this project title: "[Feature]" -labels: '' -assignees: '' - +labels: "" +assignees: "" --- **Is your feature request related to a problem? Please describe.** diff --git a/.github/workflows/check-spelling.yml b/.github/workflows/check-spelling.yml index d5ac2de..f7a4658 100644 --- a/.github/workflows/check-spelling.yml +++ b/.github/workflows/check-spelling.yml @@ -9,6 +9,9 @@ on: branches: - main +permissions: + contents: read + jobs: build: name: Check Spelling @@ -16,9 +19,11 @@ jobs: steps: - name: Checkout Code - uses: actions/checkout@v3 + uses: actions/checkout@v6 + with: + persist-credentials: false - name: Check Spelling - uses: codespell-project/actions-codespell@master + uses: codespell-project/actions-codespell@v2 with: check_filenames: true diff --git a/.github/workflows/linter.yml b/.github/workflows/linter.yml index 756f25c..d76e42a 100644 --- a/.github/workflows/linter.yml +++ b/.github/workflows/linter.yml @@ -9,6 +9,10 @@ on: branches: - main +permissions: + contents: read + statuses: write + jobs: build: name: Lint Code Base @@ -16,19 +20,22 @@ jobs: steps: - name: Checkout Code - uses: actions/checkout@v2 + uses: actions/checkout@v6 with: # Full git history is needed to get a proper # list of changed files within `super-linter` fetch-depth: 0 + persist-credentials: false - name: Lint Code Base - uses: docker://ghcr.io/github/super-linter:slim-v4 + uses: super-linter/super-linter/slim@v8.2.1 env: LINTER_RULES_PATH: / VALIDATE_ALL_CODEBASE: true VALIDATE_JSCPD: false VALIDATE_GITLEAKS: false + VALIDATE_GITHUB_ACTIONS_ZIZMOR: false + VALIDATE_PYTHON_RUFF_FORMAT: false PYTHON_PYLINT_CONFIG_FILE: .pylintrc DEFAULT_BRANCH: main GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} diff --git a/.github/workflows/pytest.yml b/.github/workflows/pytest.yml index da2a0c3..4c95986 100644 --- a/.github/workflows/pytest.yml +++ b/.github/workflows/pytest.yml @@ -6,6 +6,9 @@ on: branches: - main +permissions: + contents: read + jobs: build: runs-on: ubuntu-latest @@ -14,13 +17,15 @@ jobs: python-version: ["3.10", "3.11", "3.12", "3.13", "3.14"] steps: - - uses: actions/checkout@v4 + - uses: actions/checkout@v6 + with: + persist-credentials: false - name: Set up Python ${{ matrix.python-version }} - uses: actions/setup-python@v4 + uses: actions/setup-python@v6 with: python-version: ${{ matrix.python-version }} - name: Install uv - uses: astral-sh/setup-uv@v3 + uses: astral-sh/setup-uv@v7 - name: Install dependencies run: | uv venv diff --git a/CODE_OF_CONDUCT.md b/CODE_OF_CONDUCT.md index ac5f6c4..14315fd 100644 --- a/CODE_OF_CONDUCT.md +++ b/CODE_OF_CONDUCT.md @@ -1,4 +1,3 @@ - # Contributor Covenant Code of Conduct ## Our Pledge @@ -18,23 +17,23 @@ diverse, inclusive, and healthy community. Examples of behavior that contributes to a positive environment for our community include: -* Demonstrating empathy and kindness toward other people -* Being respectful of differing opinions, viewpoints, and experiences -* Giving and gracefully accepting constructive feedback -* Accepting responsibility and apologizing to those affected by our mistakes, +- Demonstrating empathy and kindness toward other people +- Being respectful of differing opinions, viewpoints, and experiences +- Giving and gracefully accepting constructive feedback +- Accepting responsibility and apologizing to those affected by our mistakes, and learning from the experience -* Focusing on what is best not just for us as individuals, but for the +- Focusing on what is best not just for us as individuals, but for the overall community Examples of unacceptable behavior include: -* The use of sexualized language or imagery, and sexual attention or +- The use of sexualized language or imagery, and sexual attention or advances of any kind -* Trolling, insulting or derogatory comments, and personal or political attacks -* Public or private harassment -* Publishing others' private information, such as a physical or email +- Trolling, insulting or derogatory comments, and personal or political attacks +- Public or private harassment +- Publishing others' private information, such as a physical or email address, without their explicit permission -* Other conduct which could reasonably be considered inappropriate in a +- Other conduct which could reasonably be considered inappropriate in a professional setting ## Enforcement Responsibilities @@ -107,7 +106,7 @@ Violating these terms may lead to a permanent ban. ### 4. Permanent Ban **Community Impact**: Demonstrating a pattern of violation of community -standards, including sustained inappropriate behavior, harassment of an +standards, including sustained inappropriate behavior, harassment of an individual, or aggression toward or disparagement of classes of individuals. **Consequence**: A permanent ban from any sort of public interaction within @@ -127,4 +126,3 @@ enforcement ladder](https://github.com/mozilla/diversity). For answers to common questions about this code of conduct, see the FAQ at . Translations are available at . - diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index 2f0b666..2d293e2 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -1,12 +1,15 @@ # Contributing + :wave: Hi there! We're thrilled that you'd like to contribute to this project. Your help is essential for making it great. ## Submitting a pull request + [Pull Requests][pulls] are used for adding new code and documents to the repository, or editing the existing code or documentation. **With write access** + 1. Clone the repository (only if you have write access) 1. Create a new branch: `git checkout -b my-branch-name` 1. Make your change @@ -14,6 +17,7 @@ Your help is essential for making it great. 1. Pat yourself on the back and wait for your pull request to be reviewed and merged. **Without write access** + 1. [Fork][fork] and clone the repository 1. Create a new branch: `git checkout -b my-branch-name` 1. Make your change @@ -31,12 +35,15 @@ Draft pull requests are also welcome to get feedback early on, or if there is so - Open a pull request ## Releasing + If you are the current maintainer of this code: + 1. Update `README.md` to reflect new version number in the suggested workflow file section 2. Draft [Release](https://help.github.com/en/github/administering-a-repository/managing-releases-in-a-repository) document explaining details of Release 3. Look for approval from @prestoncarman or @KirtOnthank ## Resources + - [How to Contribute to Open Source](https://opensource.guide/how-to-contribute/) - [Using Pull Requests](https://help.github.com/articles/about-pull-requests/) - [GitHub Help](https://help.github.com) diff --git a/README.md b/README.md index 9cec401..19f8668 100644 --- a/README.md +++ b/README.md @@ -1,23 +1,23 @@ # Tank Controller in Python + [![All Contributors](https://img.shields.io/badge/all_contributors-9-orange.svg?style=flat-square)](#contributors-) - + ## Project Motivations Update the `TankController` code from C++ to Python and run on a Raspberry Pico. - ## Requirements To set up and run this project, the system must meet the following requirements: - **uv**: The python project package manager must be installed. Learn more at [https://docs.astral.sh/uv/](https://docs.astral.sh/uv/). -Format contributions with `uv run black .` + Format contributions with `uv run black .` - **tkinter**: The Python GUI to test locally. Often installed separately as `python3-tk`. -Verify with `python -m tkinter`. A small GUI window should appear if Tkinter is installed correctly. + Verify with `python -m tkinter`. A small GUI window should appear if Tkinter is installed correctly. ### Mac Requirements @@ -31,40 +31,39 @@ brew install python-tk@3.14 To run in a local environment with mocked devices (with the UI State Machine integrated) -``` sh +```sh ./run_gui.sh ``` ## Features -| View Commands | Set Commands | -| ----------------------- | ------------------- | -| View IP and MAC | pH calibration | -| View free memory | Clear pH calibra | -| View Google mins | Clear Temp calib | -| View log file | Set chill/heat | -| View pH slope | Set Google mins | -| View PID | Set KD | -| View tank ID | Set KI | -| View temp cal | Set KP | -| View time | Set pH target | -| View version | Set pH w sine | -| | Set Temp w sine | -| | PID on/off | -| | Set Tank ID | -| | Temp calibration | -| | Set temperature | -| | Set date/time | +| View Commands | Set Commands | +| ---------------- | ---------------- | +| View IP and MAC | pH calibration | +| View free memory | Clear pH calibra | +| View Google mins | Clear Temp calib | +| View log file | Set chill/heat | +| View pH slope | Set Google mins | +| View PID | Set KD | +| View tank ID | Set KI | +| View temp cal | Set KP | +| View time | Set pH target | +| View version | Set pH w sine | +| | Set Temp w sine | +| | PID on/off | +| | Set Tank ID | +| | Temp calibration | +| | Set temperature | +| | Set date/time | ## Testing To perform Pytest tests for the devices and UI states. -``` sh +```sh ./test.sh ``` - ## Contributors ✨ Thanks goes to these wonderful people ([emoji key](https://allcontributors.org/docs/en/emoji-key)): diff --git a/format.sh b/format.sh index 01c5ec3..98e9960 100755 --- a/format.sh +++ b/format.sh @@ -12,6 +12,8 @@ uv run black . uv run isort . uv run flake8 . uv run pylint main.py src/ tests/ +uv run ruff check --fix . +uv run ruff format . # Clean up find . -name ".pytest_cache" -type d -exec /bin/rm -rf {} + diff --git a/pyproject.toml b/pyproject.toml index 0cad624..4cb6654 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -34,4 +34,8 @@ dev = [ "pytest", "pytest-cov", "pytest-mock", + "ruff", ] + +[tool.ruff.lint] +extend-select = ["B"] diff --git a/src/devices/library.py b/src/devices/library.py index d155931..4b2e2da 100644 --- a/src/devices/library.py +++ b/src/devices/library.py @@ -4,6 +4,7 @@ # pylint: disable=unused-import, ungrouped-imports, wrong-import-position # mypy: ignore-errors +# ruff: noqa: F401 from src import mock_config diff --git a/uv.lock b/uv.lock index a36de88..ec0cc21 100644 --- a/uv.lock +++ b/uv.lock @@ -149,12 +149,12 @@ wheels = [ ] [[package]] -name = "asteroid" -version = "4.0.1" +name = "astroid" +version = "4.0.3" source = { registry = "https://pypi.org/simple" } -sdist = { url = "https://files.pythonhosted.org/packages/a7/d1/6eee8726a863f28ff50d26c5eacb1a590f96ccbb273ce0a8c047ffb10f5a/astroid-4.0.1.tar.gz", hash = "sha256:0d778ec0def05b935e198412e62f9bcca8b3b5c39fdbe50b0ba074005e477aab", size = 405414, upload-time = "2025-10-11T15:15:42.6Z" } +sdist = { url = "https://files.pythonhosted.org/packages/a1/ca/c17d0f83016532a1ad87d1de96837164c99d47a3b6bbba28bd597c25b37a/astroid-4.0.3.tar.gz", hash = "sha256:08d1de40d251cc3dc4a7a12726721d475ac189e4e583d596ece7422bc176bda3", size = 406224, upload-time = "2026-01-03T22:14:26.096Z" } wheels = [ - { url = "https://files.pythonhosted.org/packages/47/f4/034361a9cbd9284ef40c8ad107955ede4efae29cbc17a059f63f6569c06a/astroid-4.0.1-py3-none-any.whl", hash = "sha256:37ab2f107d14dc173412327febf6c78d39590fdafcb44868f03b6c03452e3db0", size = 276268, upload-time = "2025-10-11T15:15:40.585Z" }, + { url = "https://files.pythonhosted.org/packages/ce/66/686ac4fc6ef48f5bacde625adac698f41d5316a9753c2b20bb0931c9d4e2/astroid-4.0.3-py3-none-any.whl", hash = "sha256:864a0a34af1bd70e1049ba1e61cee843a7252c826d97825fcee9b2fcbd9e1b14", size = 276443, upload-time = "2026-01-03T22:14:24.412Z" }, ] [[package]] @@ -480,7 +480,7 @@ name = "pylint" version = "4.0.1" source = { registry = "https://pypi.org/simple" } dependencies = [ - { name = "asteroid" }, + { name = "astroid" }, { name = "colorama", marker = "sys_platform == 'win32'" }, { name = "dill" }, { name = "isort" }, @@ -583,6 +583,32 @@ wheels = [ { url = "https://files.pythonhosted.org/packages/28/b8/27e6312e86408a44fe16bd28ee12dd98608b39f7e7e57884a24e8f29b573/pyusb-1.3.1-py3-none-any.whl", hash = "sha256:bf9b754557af4717fe80c2b07cc2b923a9151f5c08d17bdb5345dac09d6a0430", size = 58465, upload-time = "2025-01-08T23:45:00.029Z" }, ] +[[package]] +name = "ruff" +version = "0.14.13" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/50/0a/1914efb7903174b381ee2ffeebb4253e729de57f114e63595114c8ca451f/ruff-0.14.13.tar.gz", hash = "sha256:83cd6c0763190784b99650a20fec7633c59f6ebe41c5cc9d45ee42749563ad47", size = 6059504, upload-time = "2026-01-15T20:15:16.918Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/c3/ae/0deefbc65ca74b0ab1fd3917f94dc3b398233346a74b8bbb0a916a1a6bf6/ruff-0.14.13-py3-none-linux_armv6l.whl", hash = "sha256:76f62c62cd37c276cb03a275b198c7c15bd1d60c989f944db08a8c1c2dbec18b", size = 13062418, upload-time = "2026-01-15T20:14:50.779Z" }, + { url = "https://files.pythonhosted.org/packages/47/df/5916604faa530a97a3c154c62a81cb6b735c0cb05d1e26d5ad0f0c8ac48a/ruff-0.14.13-py3-none-macosx_10_12_x86_64.whl", hash = "sha256:914a8023ece0528d5cc33f5a684f5f38199bbb566a04815c2c211d8f40b5d0ed", size = 13442344, upload-time = "2026-01-15T20:15:07.94Z" }, + { url = "https://files.pythonhosted.org/packages/4c/f3/e0e694dd69163c3a1671e102aa574a50357536f18a33375050334d5cd517/ruff-0.14.13-py3-none-macosx_11_0_arm64.whl", hash = "sha256:d24899478c35ebfa730597a4a775d430ad0d5631b8647a3ab368c29b7e7bd063", size = 12354720, upload-time = "2026-01-15T20:15:09.854Z" }, + { url = "https://files.pythonhosted.org/packages/c3/e8/67f5fcbbaee25e8fc3b56cc33e9892eca7ffe09f773c8e5907757a7e3bdb/ruff-0.14.13-py3-none-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:9aaf3870f14d925bbaf18b8a2347ee0ae7d95a2e490e4d4aea6813ed15ebc80e", size = 12774493, upload-time = "2026-01-15T20:15:20.908Z" }, + { url = "https://files.pythonhosted.org/packages/6b/ce/d2e9cb510870b52a9565d885c0d7668cc050e30fa2c8ac3fb1fda15c083d/ruff-0.14.13-py3-none-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:ac5b7f63dd3b27cc811850f5ffd8fff845b00ad70e60b043aabf8d6ecc304e09", size = 12815174, upload-time = "2026-01-15T20:15:05.74Z" }, + { url = "https://files.pythonhosted.org/packages/88/00/c38e5da58beebcf4fa32d0ddd993b63dfacefd02ab7922614231330845bf/ruff-0.14.13-py3-none-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:78d2b1097750d90ba82ce4ba676e85230a0ed694178ca5e61aa9b459970b3eb9", size = 13680909, upload-time = "2026-01-15T20:15:14.537Z" }, + { url = "https://files.pythonhosted.org/packages/61/61/cd37c9dd5bd0a3099ba79b2a5899ad417d8f3b04038810b0501a80814fd7/ruff-0.14.13-py3-none-manylinux_2_17_ppc64.manylinux2014_ppc64.whl", hash = "sha256:7d0bf87705acbbcb8d4c24b2d77fbb73d40210a95c3903b443cd9e30824a5032", size = 15144215, upload-time = "2026-01-15T20:15:22.886Z" }, + { url = "https://files.pythonhosted.org/packages/56/8a/85502d7edbf98c2df7b8876f316c0157359165e16cdf98507c65c8d07d3d/ruff-0.14.13-py3-none-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:a3eb5da8e2c9e9f13431032fdcbe7681de9ceda5835efee3269417c13f1fed5c", size = 14706067, upload-time = "2026-01-15T20:14:48.271Z" }, + { url = "https://files.pythonhosted.org/packages/7e/2f/de0df127feb2ee8c1e54354dc1179b4a23798f0866019528c938ba439aca/ruff-0.14.13-py3-none-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:642442b42957093811cd8d2140dfadd19c7417030a7a68cf8d51fcdd5f217427", size = 14133916, upload-time = "2026-01-15T20:14:57.357Z" }, + { url = "https://files.pythonhosted.org/packages/0d/77/9b99686bb9fe07a757c82f6f95e555c7a47801a9305576a9c67e0a31d280/ruff-0.14.13-py3-none-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:4acdf009f32b46f6e8864af19cbf6841eaaed8638e65c8dac845aea0d703c841", size = 13859207, upload-time = "2026-01-15T20:14:55.111Z" }, + { url = "https://files.pythonhosted.org/packages/7d/46/2bdcb34a87a179a4d23022d818c1c236cb40e477faf0d7c9afb6813e5876/ruff-0.14.13-py3-none-manylinux_2_31_riscv64.whl", hash = "sha256:591a7f68860ea4e003917d19b5c4f5ac39ff558f162dc753a2c5de897fd5502c", size = 14043686, upload-time = "2026-01-15T20:14:52.841Z" }, + { url = "https://files.pythonhosted.org/packages/1a/a9/5c6a4f56a0512c691cf143371bcf60505ed0f0860f24a85da8bd123b2bf1/ruff-0.14.13-py3-none-musllinux_1_2_aarch64.whl", hash = "sha256:774c77e841cc6e046fc3e91623ce0903d1cd07e3a36b1a9fe79b81dab3de506b", size = 12663837, upload-time = "2026-01-15T20:15:18.921Z" }, + { url = "https://files.pythonhosted.org/packages/fe/bb/b920016ece7651fa7fcd335d9d199306665486694d4361547ccb19394c44/ruff-0.14.13-py3-none-musllinux_1_2_armv7l.whl", hash = "sha256:61f4e40077a1248436772bb6512db5fc4457fe4c49e7a94ea7c5088655dd21ae", size = 12805867, upload-time = "2026-01-15T20:14:59.272Z" }, + { url = "https://files.pythonhosted.org/packages/7d/b3/0bd909851e5696cd21e32a8fc25727e5f58f1934b3596975503e6e85415c/ruff-0.14.13-py3-none-musllinux_1_2_i686.whl", hash = "sha256:6d02f1428357fae9e98ac7aa94b7e966fd24151088510d32cf6f902d6c09235e", size = 13208528, upload-time = "2026-01-15T20:15:03.732Z" }, + { url = "https://files.pythonhosted.org/packages/3b/3b/e2d94cb613f6bbd5155a75cbe072813756363eba46a3f2177a1fcd0cd670/ruff-0.14.13-py3-none-musllinux_1_2_x86_64.whl", hash = "sha256:e399341472ce15237be0c0ae5fbceca4b04cd9bebab1a2b2c979e015455d8f0c", size = 13929242, upload-time = "2026-01-15T20:15:11.918Z" }, + { url = "https://files.pythonhosted.org/packages/6a/c5/abd840d4132fd51a12f594934af5eba1d5d27298a6f5b5d6c3be45301caf/ruff-0.14.13-py3-none-win32.whl", hash = "sha256:ef720f529aec113968b45dfdb838ac8934e519711da53a0456038a0efecbd680", size = 12919024, upload-time = "2026-01-15T20:14:43.647Z" }, + { url = "https://files.pythonhosted.org/packages/c2/55/6384b0b8ce731b6e2ade2b5449bf07c0e4c31e8a2e68ea65b3bafadcecc5/ruff-0.14.13-py3-none-win_amd64.whl", hash = "sha256:6070bd026e409734b9257e03e3ef18c6e1a216f0435c6751d7a8ec69cb59abef", size = 14097887, upload-time = "2026-01-15T20:15:01.48Z" }, + { url = "https://files.pythonhosted.org/packages/4d/e1/7348090988095e4e39560cfc2f7555b1b2a7357deba19167b600fdf5215d/ruff-0.14.13-py3-none-win_arm64.whl", hash = "sha256:7ab819e14f1ad9fe39f246cfcc435880ef7a9390d81a2b6ac7e01039083dd247", size = 13080224, upload-time = "2026-01-15T20:14:45.853Z" }, +] + [[package]] name = "setuptools" version = "80.9.0" @@ -634,6 +660,7 @@ dev = [ { name = "pytest" }, { name = "pytest-cov" }, { name = "pytest-mock" }, + { name = "ruff" }, ] [package.metadata] @@ -656,6 +683,7 @@ requires-dist = [ { name = "pytest", marker = "extra == 'dev'" }, { name = "pytest-cov", marker = "extra == 'dev'" }, { name = "pytest-mock", marker = "extra == 'dev'" }, + { name = "ruff", marker = "extra == 'dev'" }, ] provides-extras = ["dev"] diff --git a/zizmor.yml b/zizmor.yml new file mode 100644 index 0000000..c7978a5 --- /dev/null +++ b/zizmor.yml @@ -0,0 +1,6 @@ +rules: + unpinned-uses: + ignore: + - check-spelling.yml + - linter.yml + - pytest.yml