Browse Source

drop compatibility with python3.9

Fabian Peter Hammerle 3 weeks ago
parent
commit
2c7e6ed0f9

+ 4 - 5
.github/workflows/python.yml

@@ -1,3 +1,4 @@
+---
 # sync with https://github.com/fphammerle/ical2vdir/blob/master/.github/workflows/python.yml
 
 # https://help.github.com/en/actions/reference/workflow-syntax-for-github-actions
@@ -14,7 +15,7 @@ on:
 
 jobs:
   code-format:
-    runs-on: ubuntu-22.04
+    runs-on: ubuntu-24.04
     strategy:
       matrix: {python-version: ['3.13']}
     steps:
@@ -29,11 +30,10 @@ jobs:
     - run: pipenv graph
     - run: pipenv run black --check .
   tests:
-    runs-on: ubuntu-22.04
+    runs-on: ubuntu-24.04
     strategy:
       matrix:
         python-version:
-        - '3.9'
         - '3.10'
         - '3.11'
         - '3.12'
@@ -57,8 +57,7 @@ jobs:
       env:
         PYTHON_VERSION: ${{ matrix.python-version }}
     - run: pipenv graph
-    - run: >-
-        pipenv run pytest --cov="$(cat *.egg-info/top_level.txt)"
+    - run: pipenv run pytest --cov="$(cat *.egg-info/top_level.txt)"
         --cov-report=term-missing --cov-fail-under=100
     - run: pipenv run pylint "$(cat *.egg-info/top_level.txt)"
     # https://github.com/PyCQA/pylint/issues/352

+ 2 - 0
CHANGELOG.md

@@ -5,6 +5,8 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),
 and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
 
 ## [Unreleased]
+### Removed
+- compatibility with `python3.9`
 
 ## [1.2.0] - 2025-09-07
 ## Added

+ 6 - 7
Pipfile

@@ -1,7 +1,7 @@
 [[source]]
+name = "pypi"
 url = "https://pypi.org/simple"
 verify_ssl = true
-name = "pypi"
 
 [packages]
 systemctl-mqtt = {editable = true, path = "."}
@@ -14,7 +14,11 @@ pytest = "*"
 pytest-asyncio = "*"
 pytest-cov = "*"
 
-# python<3.11 compatibility
+# python3.10 compatibility
+# >   File "…/python3.10/site-packages/pytest_asyncio/plugin.py", line 60, in …
+# >     from backports.asyncio.runner import Runner
+# > ModuleNotFoundError: No module named 'backports'
+"backports.asyncio.runner" = {markers = "python_version < '3.11'"}
 # >    File "[...]/lib/python3.10/site-packages/_pytest/_code/code.py", line 60, in <module>
 # >     from exceptiongroup import BaseExceptionGroup
 # > ModuleNotFoundError: No module named 'exceptiongroup'
@@ -23,11 +27,6 @@ exceptiongroup = {markers = "python_version < '3.11'"}
 # >     import tomli as tomllib
 # > ModuleNotFoundError: No module named 'tomli'
 tomli = {markers = "python_version < '3.11'"}
-# remove `"markers": "python_version >= '3.11'"` to workaround:
-# >   File "[...]/lib/python3.7/site-packages/pylint/lint/parallel.py", line 13, in <module>
-# >     import dill
-# > ModuleNotFoundError: No module named 'dill'
-dill = {markers = "python_version >= '0'"}
 
 [requires]
 python_version = "3"

+ 168 - 152
Pipfile.lock

@@ -1,7 +1,7 @@
 {
     "_meta": {
         "hash": {
-            "sha256": "915d7f16e1258ec66edd3c4f4fd972f563e23fc0e9f8f56eabd41bcb76c56821"
+            "sha256": "1f3cb39f0fdfd1e235c28f26842ebdcb4728fd99065001685283009066c7fcec"
         },
         "pipfile-spec": 6,
         "requires": {
@@ -18,11 +18,11 @@
     "default": {
         "aiomqtt": {
             "hashes": [
-                "sha256:127926717bd6b012d1630f9087f24552eb9c4af58205bc2964f09d6e304f7e63",
-                "sha256:312feebe20bc76dc7c20916663011f3bd37aa6f42f9f687a19a1c58308d80d47"
+                "sha256:721296e2b79df5f6c7c4dfc91700ae0166953a4127735c92637859619dbd84e4",
+                "sha256:ab0f18fc5b7ffaa57451c407417d674db837b00a9c7d953cccd02be64f046c17"
             ],
             "markers": "python_version >= '3.8' and python_version < '4.0'",
-            "version": "==2.3.0"
+            "version": "==2.4.0"
         },
         "jeepney": {
             "hashes": [
@@ -48,152 +48,168 @@
     "develop": {
         "astroid": {
             "hashes": [
-                "sha256:1e5a5011af2920c7c67a53f65d536d65bfa7116feeaf2354d8b94f29573bb0ce",
-                "sha256:54c760ae8322ece1abd213057c4b5bba7c49818853fc901ef09719a60dbf9dec"
+                "sha256:ac8fb7ca1c08eb9afec91ccc23edbd8ac73bb22cbdd7da1d488d9fb8d6579070",
+                "sha256:d7546c00a12efc32650b19a2bb66a153883185d3179ab0d4868086f807338b9b"
             ],
-            "markers": "python_full_version >= '3.9.0'",
-            "version": "==3.3.11"
+            "markers": "python_full_version >= '3.10.0'",
+            "version": "==4.0.2"
+        },
+        "backports.asyncio.runner": {
+            "hashes": [
+                "sha256:a5aa7b2b7d8f8bfcaa2b57313f70792df84e32a2a746f585213373f900b42162",
+                "sha256:0da0a936a8aeb554eccb426dc55af3ba63bcdc69fa1a600b5bb305413a4477b5"
+            ],
+            "markers": "python_version < '3.11'",
+            "version": "==1.2.0"
         },
         "black": {
             "hashes": [
-                "sha256:0172a012f725b792c358d57fe7b6b6e8e67375dd157f64fa7a3097b3ed3e2175",
-                "sha256:0474bca9a0dd1b51791fcc507a4e02078a1c63f6d4e4ae5544b9848c7adfb619",
-                "sha256:154b06d618233fe468236ba1f0e40823d4eb08b26f5e9261526fde34916b9140",
-                "sha256:1b9dc70c21ef8b43248f1d86aedd2aaf75ae110b958a7909ad8463c4aa0880b0",
-                "sha256:2ab0ce111ef026790e9b13bd216fa7bc48edd934ffc4cbf78808b235793cbc92",
-                "sha256:3bec74ee60f8dfef564b573a96b8930f7b6a538e846123d5ad77ba14a8d7a64f",
-                "sha256:456386fe87bad41b806d53c062e2974615825c7a52159cde7ccaeb0695fa28fa",
-                "sha256:474b34c1342cdc157d307b56c4c65bce916480c4a8f6551fdc6bf9b486a7c4ae",
-                "sha256:77e7060a00c5ec4b3367c55f39cf9b06e68965a4f2e61cecacd6d0d9b7ec945a",
-                "sha256:846d58e3ce7879ec1ffe816bb9df6d006cd9590515ed5d17db14e17666b2b357",
-                "sha256:8e46eecf65a095fa62e53245ae2795c90bdecabd53b50c448d0a8bcd0d2e74c4",
-                "sha256:9101ee58ddc2442199a25cb648d46ba22cd580b00ca4b44234a324e3ec7a0f7e",
-                "sha256:a16b14a44c1af60a210d8da28e108e13e75a284bf21a9afa6b4571f96ab8bb9d",
-                "sha256:aaf319612536d502fdd0e88ce52d8f1352b2c0a955cc2798f79eeca9d3af0608",
-                "sha256:b756fc75871cb1bcac5499552d771822fd9db5a2bb8db2a7247936ca48f39831",
-                "sha256:c0372a93e16b3954208417bfe448e09b0de5cc721d521866cd9e0acac3c04a1f",
-                "sha256:ce41ed2614b706fd55fd0b4a6909d06b5bab344ffbfadc6ef34ae50adba3d4f7",
-                "sha256:d119957b37cc641596063cd7db2656c5be3752ac17877017b2ffcdb9dfc4d2b1",
-                "sha256:e3c1f4cd5e93842774d9ee4ef6cd8d17790e65f44f7cdbaab5f2cf8ccf22a823",
-                "sha256:e593466de7b998374ea2585a471ba90553283fb9beefcfa430d84a2651ed5933",
-                "sha256:ef69351df3c84485a8beb6f7b8f9721e2009e20ef80a8d619e2d1788b7816d47",
-                "sha256:f96b6726d690c96c60ba682955199f8c39abc1ae0c3a494a9c62c0184049a713"
+                "sha256:0a1d40348b6621cc20d3d7530a5b8d67e9714906dfd7346338249ad9c6cedf2b",
+                "sha256:0c0f7c461df55cf32929b002335883946a4893d759f2df343389c4396f3b6b37",
+                "sha256:1032639c90208c15711334d681de2e24821af0575573db2810b0763bcd62e0f0",
+                "sha256:35690a383f22dd3e468c85dc4b915217f87667ad9cce781d7b42678ce63c4170",
+                "sha256:43945853a31099c7c0ff8dface53b4de56c41294fa6783c0441a8b1d9bf668bc",
+                "sha256:51c65d7d60bb25429ea2bf0731c32b2a2442eb4bd3b2afcb47830f0b13e58bfd",
+                "sha256:5bd4a22a0b37401c8e492e994bce79e614f91b14d9ea911f44f36e262195fdda",
+                "sha256:6cb2d54a39e0ef021d6c5eef442e10fd71fcb491be6413d083a320ee768329dd",
+                "sha256:6cced12b747c4c76bc09b4db057c319d8545307266f41aaee665540bc0e04e96",
+                "sha256:7eebd4744dfe92ef1ee349dc532defbf012a88b087bb7ddd688ff59a447b080e",
+                "sha256:80e7486ad3535636657aa180ad32a7d67d7c273a80e12f1b4bfa0823d54e8fac",
+                "sha256:895571922a35434a9d8ca67ef926da6bc9ad464522a5fe0db99b394ef1c0675a",
+                "sha256:92285c37b93a1698dcbc34581867b480f1ba3a7b92acf1fe0467b04d7a4da0dc",
+                "sha256:936c4dd07669269f40b497440159a221ee435e3fddcf668e0c05244a9be71993",
+                "sha256:9815ccee1e55717fe9a4b924cae1646ef7f54e0f990da39a34fc7b264fcf80a2",
+                "sha256:9a323ac32f5dc75ce7470501b887250be5005a01602e931a15e45593f70f6e08",
+                "sha256:a3bb5ce32daa9ff0605d73b6f19da0b0e6c1f8f2d75594db539fdfed722f2b06",
+                "sha256:aa211411e94fdf86519996b7f5f05e71ba34835d8f0c0f03c00a26271da02664",
+                "sha256:ae263af2f496940438e5be1a0c1020e13b09154f3af4df0835ea7f9fe7bfa409",
+                "sha256:cb4f4b65d717062191bdec8e4a442539a8ea065e6af1c4f4d36f0cdb5f71e170",
+                "sha256:d81a44cbc7e4f73a9d6ae449ec2317ad81512d1e7dce7d57f6333fd6259737bc",
+                "sha256:dae49ef7369c6caa1a1833fd5efb7c3024bb7e4499bf64833f65ad27791b1545",
+                "sha256:e3f562da087791e96cefcd9dda058380a442ab322a02e222add53736451f604b",
+                "sha256:ec311e22458eec32a807f029b2646f661e6859c3f61bc6d9ffb67958779f392e",
+                "sha256:f42c0ea7f59994490f4dccd64e6b2dd49ac57c7c84f38b8faab50f8759db245c",
+                "sha256:f9786c24d8e9bd5f20dc7a7f0cdd742644656987f6ea6947629306f937726c03"
             ],
             "index": "pypi",
             "markers": "python_version >= '3.9'",
-            "version": "==25.9.0"
+            "version": "==25.11.0"
         },
         "click": {
             "hashes": [
-                "sha256:9b9f285302c6e3064f4330c05f05b81945b2a39544279343e6e7c5f27a9baddc",
-                "sha256:e7b8232224eba16f4ebe410c25ced9f7875cb5f3263ffc93cc3e8da705e229c4"
+                "sha256:12ff4785d337a1bb490bb7e9c2b1ee5da3112e94a8622f26a6c77f5d2fc6842a",
+                "sha256:981153a64e25f12d547d3426c367a4857371575ee7ad18df2a6183ab0545b2a6"
             ],
             "markers": "python_version >= '3.10'",
-            "version": "==8.3.0"
+            "version": "==8.3.1"
         },
         "coverage": {
             "extras": [
                 "toml"
             ],
             "hashes": [
-                "sha256:073711de3181b2e204e4870ac83a7c4853115b42e9cd4d145f2231e12d670930",
-                "sha256:081b98395ced0d9bcf60ada7661a0b75f36b78b9d7e39ea0790bb4ed8da14747",
-                "sha256:0de434f4fbbe5af4fa7989521c655c8c779afb61c53ab561b64dcee6149e4c65",
-                "sha256:0e93b1476b79eae849dc3872faeb0bf7948fd9ea34869590bc16a2a00b9c82a7",
-                "sha256:0f3f56e4cb573755e96a16501a98bf211f100463d70275759e73f3cbc00d4f27",
-                "sha256:0f7cb359a448e043c576f0da00aa8bfd796a01b06aa610ca453d4dde09cc1034",
-                "sha256:10356fdd33a7cc06e8051413140bbdc6f972137508a3572e3f59f805cd2832fd",
-                "sha256:137921f2bac5559334ba66122b753db6dc5d1cf01eb7b64eb412bb0d064ef35b",
-                "sha256:160c00a5e6b6bdf4e5984b0ef21fc860bc94416c41b7df4d63f536d17c38902e",
-                "sha256:2195f8e16ba1a44651ca684db2ea2b2d4b5345da12f07d9c22a395202a05b23c",
-                "sha256:282b1b20f45df57cc508c1e033403f02283adfb67d4c9c35a90281d81e5c52c5",
-                "sha256:28395ca3f71cd103b8c116333fa9db867f3a3e1ad6a084aa3725ae002b6583bc",
-                "sha256:2904271c80898663c810a6b067920a61dd8d38341244a3605bd31ab55250dad5",
-                "sha256:2b38261034fda87be356f2c3f42221fdb4171c3ce7658066ae449241485390d5",
-                "sha256:2e4c33e6378b9d52d3454bd08847a8651f4ed23ddbb4a0520227bd346382bbc6",
-                "sha256:388d80e56191bf846c485c14ae2bc8898aa3124d9d35903fef7d907780477634",
-                "sha256:3e23dd5408fe71a356b41baa82892772a4cefcf758f2ca3383d2aa39e1b7a003",
-                "sha256:3fb99d0786fe17b228eab663d16bee2288e8724d26a199c29325aac4b0319b9b",
-                "sha256:441c357d55f4936875636ef2cfb3bee36e466dcf50df9afbd398ce79dba1ebb7",
-                "sha256:4cec13817a651f8804a86e4f79d815b3b28472c910e099e4d5a0e8a3b6a1d4cb",
-                "sha256:5aea98383463d6e1fa4e95416d8de66f2d0cb588774ee20ae1b28df826bcb619",
-                "sha256:5b15a87265e96307482746d86995f4bff282f14b027db75469c446da6127433b",
-                "sha256:5b2dd6059938063a2c9fee1af729d4f2af28fd1a545e9b7652861f0d752ebcea",
-                "sha256:5e75e37f23eb144e78940b40395b42f2321951206a4f50e23cfd6e8a198d3ceb",
-                "sha256:6008a021907be8c4c02f37cdc3ffb258493bdebfeaf9a839f9e71dfdc47b018e",
-                "sha256:61c950fc33d29c91b9e18540e1aed7d9f6787cc870a3e4032493bbbe641d12fc",
-                "sha256:628055297f3e2aa181464c3808402887643405573eb3d9de060d81531fa79d32",
-                "sha256:675824a363cc05781b1527b39dc2587b8984965834a748177ee3c37b64ffeafb",
-                "sha256:689920ecfd60f992cafca4f5477d55720466ad2c7fa29bb56ac8d44a1ac2b47a",
-                "sha256:692d70ea725f471a547c305f0d0fc6a73480c62fb0da726370c088ab21aed282",
-                "sha256:6937347c5d7d069ee776b2bf4e1212f912a9f1f141a429c475e6089462fcecc5",
-                "sha256:6b3039e2ca459a70c79523d39347d83b73f2f06af5624905eba7ec34d64d80b5",
-                "sha256:6e31b8155150c57e5ac43ccd289d079eb3f825187d7c66e755a055d2c85794c6",
-                "sha256:70e7bfbd57126b5554aa482691145f798d7df77489a177a6bef80de78860a356",
-                "sha256:752a3005a1ded28f2f3a6e8787e24f28d6abe176ca64677bcd8d53d6fe2ec08a",
-                "sha256:7d79dabc0a56f5af990cc6da9ad1e40766e82773c075f09cc571e2076fef882e",
-                "sha256:7eb68d356ba0cc158ca535ce1381dbf2037fa8cb5b1ae5ddfc302e7317d04144",
-                "sha256:80b1695cf7c5ebe7b44bf2521221b9bb8cdf69b1f24231149a7e3eb1ae5fa2fb",
-                "sha256:851430a9a361c7a8484a36126d1d0ff8d529d97385eacc8dfdc9bfc8c2d2cbe4",
-                "sha256:856986eadf41f52b214176d894a7de05331117f6035a28ac0016c0f63d887629",
-                "sha256:86b9b59f2b16e981906e9d6383eb6446d5b46c278460ae2c36487667717eccf1",
-                "sha256:8953746d371e5695405806c46d705a3cd170b9cc2b9f93953ad838f6c1e58612",
-                "sha256:8cdbe264f11afd69841bd8c0d83ca10b5b32853263ee62e6ac6a0ab63895f972",
-                "sha256:8dd5af36092430c2b075cee966719898f2ae87b636cefb85a653f1d0ba5d5393",
-                "sha256:8e0c38dc289e0508ef68ec95834cb5d2e96fdbe792eaccaa1bccac3966bbadcc",
-                "sha256:90558c35af64971d65fbd935c32010f9a2f52776103a259f1dee865fe8259352",
-                "sha256:90cb5b1a4670662719591aa92d0095bb41714970c0b065b02a2610172dbf0af6",
-                "sha256:92be86fcb125e9bda0da7806afd29a3fd33fdf58fba5d60318399adf40bf37d0",
-                "sha256:92c4ecf6bf11b2e85fd4d8204814dc26e6a19f0c9d938c207c5cb0eadfcabbe3",
-                "sha256:95d91d7317cde40a1c249d6b7382750b7e6d86fad9d8eaf4fa3f8f44cf171e80",
-                "sha256:961834e2f2b863a0e14260a9a273aff07ff7818ab6e66d2addf5628590c628f9",
-                "sha256:9702b59d582ff1e184945d8b501ffdd08d2cee38d93a2206aa5f1365ce0b8d78",
-                "sha256:98cede73eb83c31e2118ae8d379c12e3e42736903a8afcca92a7218e1f2903b0",
-                "sha256:99c4283e2a0e147b9c9cc6bc9c96124de9419d6044837e9799763a0e29a7321a",
-                "sha256:99e1a305c7765631d74b98bf7dbf54eeea931f975e80f115437d23848ee8c27c",
-                "sha256:a517feaf3a0a3eca1ee985d8373135cfdedfbba3882a5eab4362bda7c7cf518d",
-                "sha256:a80f7aef9535442bdcf562e5a0d5a5538ce8abe6bb209cfbf170c462ac2c2a32",
-                "sha256:ac765b026c9f33044419cbba1da913cfb82cca1b60598ac1c7a5ed6aac4621a0",
-                "sha256:acf36b8268785aad739443fa2780c16260ee3fa09d12b3a70f772ef100939d80",
-                "sha256:adec1d980fa07e60b6ef865f9e5410ba760e4e1d26f60f7e5772c73b9a5b0713",
-                "sha256:b0353b0f0850d49ada66fdd7d0c7cdb0f86b900bb9e367024fd14a60cecc1e27",
-                "sha256:b37201ce4a458c7a758ecc4efa92fa8ed783c66e0fa3c42ae19fc454a0792153",
-                "sha256:bf9a19f5012dab774628491659646335b1928cfc931bf8d97b0d5918dd58033c",
-                "sha256:c61fc91ab80b23f5fddbee342d19662f3d3328173229caded831aa0bd7595460",
-                "sha256:c68018e4fc4e14b5668f1353b41ccf4bc83ba355f0e1b3836861c6f042d89ac1",
-                "sha256:c706db3cabb7ceef779de68270150665e710b46d56372455cd741184f3868d8f",
-                "sha256:c83f6afb480eae0313114297d29d7c295670a41c11b274e6bca0c64540c1ce7b",
-                "sha256:c8a3ec16e34ef980a46f60dc6ad86ec60f763c3f2fa0db6d261e6e754f72e945",
-                "sha256:c9a8b7a34a4de3ed987f636f71881cd3b8339f61118b1aa311fbda12741bff0b",
-                "sha256:cd4b2b0707fc55afa160cd5fc33b27ccbf75ca11d81f4ec9863d5793fc6df56a",
-                "sha256:d6b9ae13d5d3e8aeca9ca94198aa7b3ebbc5acfada557d724f2a1f03d2c0b0df",
-                "sha256:d8fd7879082953c156d5b13c74aa6cca37f6a6f4747b39538504c3f9c63d043d",
-                "sha256:d9369a23186d189b2fc95cc08b8160ba242057e887d766864f7adf3c46b2df21",
-                "sha256:db4a1d897bbbe7339946ffa2fe60c10cc81c43fab8b062d3fcb84188688174a4",
-                "sha256:df4ec1f8540b0bcbe26ca7dd0f541847cc8a108b35596f9f91f59f0c060bfdd2",
-                "sha256:e132b9152749bd33534e5bd8565c7576f135f157b4029b975e15ee184325f528",
-                "sha256:e3fb1fa01d3598002777dd259c0c2e6d9d5e10e7222976fc8e03992f972a2cba",
-                "sha256:e41be6f0f19da64af13403e52f2dec38bbc2937af54df8ecef10850ff8d35301",
-                "sha256:ec98435796d2624d6905820a42f82149ee9fc4f2d45c2c5bc5a44481cc50db62",
-                "sha256:efeda443000aa23f276f4df973cb82beca682fd800bb119d19e80504ffe53ec2",
-                "sha256:f2a6a8e06bbda06f78739f40bfb56c45d14eb8249d0f0ea6d4b3d48e1f7c695d",
-                "sha256:f32ff80e7ef6a5b5b606ea69a36e97b219cd9dc799bcf2963018a4d8f788cfbf",
-                "sha256:f35ed9d945bece26553d5b4c8630453169672bea0050a564456eb88bdffd927e",
-                "sha256:f644a3ae5933a552a29dbb9aa2f90c677a875f80ebea028e5a52a4f429044b90",
-                "sha256:f863c08f4ff6b64fa8045b1e3da480f5374779ef187f07b82e0538c68cb4ff8e",
-                "sha256:fc53ba868875bfbb66ee447d64d6413c2db91fddcfca57025a0e7ab5b07d5862",
-                "sha256:ff8a991f70f4c0cf53088abf1e3886edcc87d53004c7bb94e78650b4d3dac3b5",
-                "sha256:ffea0575345e9ee0144dfe5701aa17f3ba546f8c3bb48db62ae101afb740e7d6"
+                "sha256:004cdcea3457c0ea3233622cd3464c1e32ebba9b41578421097402bee6461b63",
+                "sha256:0542ddf6107adbd2592f29da9f59f5d9cff7947b5bb4f734805085c327dcffaa",
+                "sha256:05fd3fb6edff0c98874d752013588836f458261e5eba587afe4c547bba544afd",
+                "sha256:074e6a5cd38e06671580b4d872c1a67955d4e69639e4b04e87fc03b494c1f060",
+                "sha256:07bc7745c945a6d95676953e86ba7cebb9f11de7773951c387f4c07dc76d03f5",
+                "sha256:08c0bcf932e47795c49f0406054824b9d45671362dfc4269e0bc6e4bff010704",
+                "sha256:097acc18bedf2c6e3144eaf09b5f6034926c3c9bb9e10574ffd0942717232507",
+                "sha256:0c986537abca9b064510f3fd104ba33e98d3036608c7f2f5537f869bc10e1ee5",
+                "sha256:0dba4da36730e384669e05b765a2c49f39514dd3012fcc0398dd66fba8d746d5",
+                "sha256:0e920567f8c3a3ce68ae5a42cf7c2dc4bb6cc389f18bff2235dd8c03fa405de5",
+                "sha256:0f59387f5e6edbbffec2281affb71cdc85e0776c1745150a3ab9b6c1d016106b",
+                "sha256:12d821de7408292530b0d241468b698bce18dd12ecaf45316149f53877885f8c",
+                "sha256:13b2066303a1c1833c654d2af0455bb009b6e1727b3883c9964bc5c2f643c1d0",
+                "sha256:1410bac9e98afd9623f53876fae7d8a5db9f5a0ac1c9e7c5188463cb4b3212e2",
+                "sha256:1451464fd855d9bd000c19b71bb7dafea9ab815741fb0bd9e813d9b671462d6f",
+                "sha256:149eccc85d48c8f06547534068c41d69a1a35322deaa4d69ba1561e2e9127e75",
+                "sha256:1e33d0bebf895c7a0905fcfaff2b07ab900885fc78bba2a12291a2cfbab014cc",
+                "sha256:200bb89fd2a8a07780eafcdff6463104dec459f3c838d980455cfa84f5e5e6e1",
+                "sha256:2376e8a9c889016f25472c452389e98bc6e54a19570b107e27cde9d47f387b64",
+                "sha256:28c5251b3ab1d23e66f1130ca0c419747edfbcb4690de19467cd616861507af7",
+                "sha256:2ec27a7a991d229213c8070d31e3ecf44d005d96a9edc30c78eaeafaa421c001",
+                "sha256:305716afb19133762e8cf62745c46c4853ad6f9eeba54a593e373289e24ea237",
+                "sha256:31663572f20bf3406d7ac00d6981c7bbbcec302539d26b5ac596ca499664de31",
+                "sha256:3224c7baf34e923ffc78cb45e793925539d640d42c96646db62dbd61bbcfa131",
+                "sha256:351511ae28e2509c8d8cae5311577ea7dd511ab8e746ffc8814a0896c3d33fbe",
+                "sha256:385977d94fc155f8731c895accdfcc3dd0d9dd9ef90d102969df95d3c637ab80",
+                "sha256:39764c6167c82d68a2d8c97c33dba45ec0ad9172570860e12191416f4f8e6e1b",
+                "sha256:3e33a968672be1394eded257ec10d4acbb9af2ae263ba05a99ff901bb863557e",
+                "sha256:4234914b8c67238a3c4af2bba648dc716aa029ca44d01f3d51536d44ac16854f",
+                "sha256:426559f105f644b69290ea414e154a0d320c3ad8a2bb75e62884731f69cf8e2c",
+                "sha256:465695268414e149bab754c54b0c45c8ceda73dd4a5c3ba255500da13984b16d",
+                "sha256:4bec8c7160688bd5a34e65c82984b25409563134d63285d8943d0599efbc448e",
+                "sha256:4c5627429f7fbff4f4131cfdd6abd530734ef7761116811a707b88b7e205afd7",
+                "sha256:4ca5f876bf41b24378ee67c41d688155f0e54cdc720de8ef9ad6544005899240",
+                "sha256:4d4ca49f5ba432b0755ebb0fc3a56be944a19a16bb33802264bbc7311622c0d1",
+                "sha256:4ebcddfcdfb4c614233cff6e9a3967a09484114a8b2e4f2c7a62dc83676ba13f",
+                "sha256:4f2bb4ee8dd40f9b2a80bb4adb2aecece9480ba1fa60d9382e8c8e0bd558e2eb",
+                "sha256:56f909a40d68947ef726ce6a34eb38f0ed241ffbe55c5007c64e616663bcbafc",
+                "sha256:5b771b59ac0dfb7f139f70c85b42717ef400a6790abb6475ebac1ecee8de782f",
+                "sha256:603c4414125fc9ae9000f17912dcfd3d3eb677d4e360b85206539240c96ea76e",
+                "sha256:60ca149a446da255d56c2a7a813b51a80d9497a62250532598d249b3cdb1a926",
+                "sha256:68c4eb92997dbaaf839ea13527be463178ac0ddd37a7ac636b8bc11a51af2428",
+                "sha256:6bb599052a974bb6cedfa114f9778fedfad66854107cf81397ec87cb9b8fbcf2",
+                "sha256:6f033dec603eea88204589175782290a038b436105a8f3637a81c4359df27832",
+                "sha256:72c8b494bd20ae1c58528b97c4a67d5cfeafcb3845c73542875ecd43924296de",
+                "sha256:77ffb3b7704eb7b9b3298a01fe4509cef70117a52d50bcba29cffc5f53dd326a",
+                "sha256:84b892e968164b7a0498ddc5746cdf4e985700b902128421bb5cec1080a6ee36",
+                "sha256:86d27d2dd7c7c5a44710565933c7dc9cd70e65ef97142e260d16d555667deef7",
+                "sha256:876a3ee7fd2613eb79602e4cdb39deb6b28c186e76124c3f29e580099ec21a87",
+                "sha256:8bba7e4743e37484ae17d5c3b8eb1ce78b564cb91b7ace2e2182b25f0f764cb5",
+                "sha256:8d16bbe566e16a71d123cd66382c1315fcd520c7573652a8074a8fe281b38c6a",
+                "sha256:8d264402fc179776d43e557e1ca4a7d953020d3ee95f7ec19cc2c9d769277f06",
+                "sha256:8f067ada2c333609b52835ca4d4868645d3b63ac04fb2b9a658c55bba7f667d3",
+                "sha256:8f4cbfff5cf01fa07464439a8510affc9df281535f41a1f5312fbd2b59b4ab5c",
+                "sha256:900580bc99c145e2561ea91a2d207e639171870d8a18756eb57db944a017d4bb",
+                "sha256:9061a3e3c92b27fd8036dafa26f25d95695b6aa2e4514ab16a254f297e664f83",
+                "sha256:90a96fcd824564eae6137ec2563bd061d49a32944858d4bdbae5c00fb10e76ac",
+                "sha256:9245bd392572b9f799261c4c9e7216bafc9405537d0f4ce3ad93afe081a12dc9",
+                "sha256:9799bd6a910961cb666196b8583ed0ee125fa225c6fdee2cbf00232b861f29d2",
+                "sha256:9a1d577c20b4334e5e814c3d5fe07fa4a8c3ae42a601945e8d7940bab811d0bd",
+                "sha256:a6b17c2b5e0b9bb7702449200f93e2d04cb04b1414c41424c08aa1e5d352da76",
+                "sha256:a730cd0824e8083989f304e97b3f884189efb48e2151e07f57e9e138ab104200",
+                "sha256:a8258f10059b5ac837232c589a350a2df4a96406d6d5f2a09ec587cbdd539655",
+                "sha256:ab6212e62ea0e1006531a2234e209607f360d98d18d532c2fa8e403c1afbdd71",
+                "sha256:abb903ffe46bd319d99979cdba350ae7016759bb69f47882242f7b93f3356055",
+                "sha256:abcea3b5f0dc44e1d01c27090bc32ce6ffb7aa665f884f1890710454113ea902",
+                "sha256:ac5d5329c9c942bbe6295f4251b135d860ed9f86acd912d418dce186de7c19ac",
+                "sha256:adb9b7b42c802bd8cb3927de8c1c26368ce50c8fdaa83a9d8551384d77537044",
+                "sha256:ae12fe90b00b71a71b69f513773310782ce01d5f58d2ceb2b7c595ab9d222094",
+                "sha256:b5cd111d3ab7390be0c07ad839235d5ad54d2ca497b5f5db86896098a77180a4",
+                "sha256:bb9d7efdb063903b3fdf77caec7b77c3066885068bdc0d44bc1b0c171033f944",
+                "sha256:c0a3b6e32457535df0d41d2d895da46434706dd85dbaf53fbc0d3bd7d914b362",
+                "sha256:c381a252317f63ca0179d2c7918e83b99a4ff3101e1b24849b999a00f9cd4f86",
+                "sha256:c713c1c528284d636cd37723b0b4c35c11190da6f932794e145fc40f8210a14a",
+                "sha256:c8be5bfcdc7832011b2652db29ed7672ce9d353dd19bce5272ca33dbcf60aaa8",
+                "sha256:c8f563b245b4ddb591e99f28e3cd140b85f114b38b7f95b2e42542f0603eb7d7",
+                "sha256:ca90ef33a152205fb6f2f0c1f3e55c50df4ef049bb0940ebba666edd4cdebc55",
+                "sha256:d60bf4d7f886989ddf80e121a7f4d140d9eac91f1d2385ce8eb6bda93d563297",
+                "sha256:d8750dd20362a1b80e3cf84f58013d4672f89663aee457ea59336df50fab6739",
+                "sha256:dd9ca2d44ed8018c90efb72f237a2a140325a4c3339971364d758e78b175f58e",
+                "sha256:e22539b676fafba17f0a90ac725f029a309eb6e483f364c86dcadee060429d46",
+                "sha256:e2a96fdc7643c9517a317553aca13b5cae9bad9a5f32f4654ce247ae4d321405",
+                "sha256:e5f4bfac975a2138215a38bda599ef00162e4143541cf7dd186da10a7f8e69f1",
+                "sha256:e8feeb5e8705835f0622af0fe7ff8d5cb388948454647086494d6c41ec142c2e",
+                "sha256:eb5069074db19a534de3859c43eec78e962d6d119f637c41c8e028c5ab3f59dd",
+                "sha256:f0b4101e2b3c6c352ff1f70b3a6fcc7c17c1ab1a91ccb7a33013cb0782af9820",
+                "sha256:f761dbcf45e9416ec4698e1a7649248005f0064ce3523a47402d1bff4af2779e",
+                "sha256:f9c96a29c6d65bd36a91f5634fef800212dff69dacdb44345c4c9783943ab0df",
+                "sha256:fb58da65e3339b3dbe266b607bb936efb983d86b00b03eb04c4ad5b442c58428",
+                "sha256:fbffc22d80d86fbe456af9abb17f7a7766e7b2101f7edaacc3535501691563f7",
+                "sha256:fdc5255eb4815babcdf236fa1a806ccb546724c8a9b129fd1ea4a5448a0bf07c",
+                "sha256:fe3425dc6021f906c6325d3c415e048e7cdb955505a94f1eb774dafc779ba203"
             ],
-            "markers": "python_version >= '3.9'",
-            "version": "==7.10.6"
+            "markers": "python_version >= '3.10'",
+            "version": "==7.11.3"
         },
         "dill": {
             "hashes": [
                 "sha256:0633f1d2df477324f53a895b02c901fb961bdbf65a17122586ea7019292cbcf0",
                 "sha256:44f54bf6412c2c8464c14e8243eb163690a9800dbe2c367330883b19c7561049"
             ],
-            "markers": "python_version >= '0' and python_version >= '0'",
+            "markers": "python_version >= '3.8'",
             "version": "==0.4.0"
         },
         "exceptiongroup": {
@@ -207,19 +223,19 @@
         },
         "iniconfig": {
             "hashes": [
-                "sha256:3abbd2e30b36733fee78f9c7f7308f2d0050e88f0087fd25c2645f63c773e1c7",
-                "sha256:9deba5723312380e77435581c6bf4935c94cbfab9b1ed33ef8d238ea168eb760"
+                "sha256:c76315c77db068650d49c5b56314774a7804df16fee4402c1f19d6d15d8c4730",
+                "sha256:f631c04d2c48c52b84d0d0549c99ff3859c98df65b3101406327ecc7d53fbf12"
             ],
-            "markers": "python_version >= '3.8'",
-            "version": "==2.1.0"
+            "markers": "python_version >= '3.10'",
+            "version": "==2.3.0"
         },
         "isort": {
             "hashes": [
-                "sha256:1cb5df28dfbc742e490c5e41bad6da41b805b0a8be7bc93cd0fb2a8a890ac450",
-                "sha256:2dc5d7f65c9678d94c88dfc29161a320eec67328bc97aad576874cb4be1e9615"
+                "sha256:1bcabac8bc3c36c7fb7b98a76c8abb18e0f841a3ba81decac7691008592499c1",
+                "sha256:5513527951aadb3ac4292a41a16cbc50dd1642432f5e8c20057d414bdafb4187"
             ],
-            "markers": "python_full_version >= '3.9.0'",
-            "version": "==6.0.1"
+            "markers": "python_full_version >= '3.10.0'",
+            "version": "==7.0.0"
         },
         "mccabe": {
             "hashes": [
@@ -300,11 +316,11 @@
         },
         "platformdirs": {
             "hashes": [
-                "sha256:abd01743f24e5287cd7a5db3752faf1a2d65353f38ec26d98e25a6db65958c85",
-                "sha256:ca753cf4d81dc309bc67b0ea38fd15dc97bc30ce419a7f58d13eb3bf14c4febf"
+                "sha256:70ddccdd7c99fc5942e9fc25636a8b34d04c24b335100223152c2803e4063312",
+                "sha256:e578a81bb873cbb89a41fcc904c7ef523cc18284b7e3b3ccf06aca1403b7ebd3"
             ],
-            "markers": "python_version >= '3.9'",
-            "version": "==4.4.0"
+            "markers": "python_version >= '3.10'",
+            "version": "==4.5.0"
         },
         "pluggy": {
             "hashes": [
@@ -324,30 +340,30 @@
         },
         "pylint": {
             "hashes": [
-                "sha256:26698de19941363037e2937d3db9ed94fb3303fdadf7d98847875345a8bb6b05",
-                "sha256:7ef94aa692a600e82fabdd17102b73fc226758218c97473c7ad67bd4cb905d83"
+                "sha256:896d09afb0e78bbf2e030cd1f3d8dc92771a51f7e46828cbc3948a89cd03433a",
+                "sha256:a427fe76e0e5355e9fb9b604fd106c419cafb395886ba7f3cebebb03f30e081d"
             ],
             "index": "pypi",
-            "markers": "python_full_version >= '3.9.0'",
-            "version": "==3.3.8"
+            "markers": "python_full_version >= '3.10.0'",
+            "version": "==4.0.3"
         },
         "pytest": {
             "hashes": [
-                "sha256:86c0d0b93306b961d58d62a4db4879f27fe25513d4b969df351abdddb3c30e01",
-                "sha256:872f880de3fc3a5bdc88a11b39c9710c3497a547cfa9320bc3c5e62fbf272e79"
+                "sha256:3e9c069ea73583e255c3b21cf46b8d3c56f6e3a1a8f6da94ccb0fcf57b9d73c8",
+                "sha256:67be0030d194df2dfa7b556f2e56fb3c3315bd5c8822c6951162b92b32ce7dad"
             ],
             "index": "pypi",
-            "markers": "python_version >= '3.9'",
-            "version": "==8.4.2"
+            "markers": "python_version >= '3.10'",
+            "version": "==9.0.1"
         },
         "pytest-asyncio": {
             "hashes": [
-                "sha256:4f024da9f1ef945e680dc68610b52550e36590a67fd31bb3b4943979a1f90ef3",
-                "sha256:d15463d13f4456e1ead2594520216b225a16f781e144f8fdf6c5bb4667c48b3f"
+                "sha256:611e26147c7f77640e6d0a92a38ed17c3e9848063698d5c93d5aa7aa11cebff5",
+                "sha256:d7f52f36d231b80ee124cd216ffb19369aa168fc10095013c6b014a34d3ee9e5"
             ],
             "index": "pypi",
-            "markers": "python_version >= '3.9'",
-            "version": "==1.0.0"
+            "markers": "python_version >= '3.10'",
+            "version": "==1.3.0"
         },
         "pytest-cov": {
             "hashes": [
@@ -360,11 +376,11 @@
         },
         "pytokens": {
             "hashes": [
-                "sha256:c9a4bfa0be1d26aebce03e6884ba454e842f186a59ea43a6d3b25af58223c044",
-                "sha256:db7b72284e480e69fb085d9f251f66b3d2df8b7166059261258ff35f50fb711b"
+                "sha256:2f932b14ed08de5fcf0b391ace2642f858f1394c0857202959000b68ed7a458a",
+                "sha256:95b2b5eaf832e469d141a378872480ede3f251a5a5041b8ec6e581d3ac71bbf3"
             ],
             "markers": "python_version >= '3.8'",
-            "version": "==0.1.10"
+            "version": "==0.3.0"
         },
         "tomli": {
             "hashes": [

+ 3 - 2
setup.py

@@ -50,7 +50,6 @@ setuptools.setup(
         "License :: OSI Approved :: GNU General Public License v3 or later (GPLv3+)",
         "Operating System :: POSIX :: Linux",
         # .github/workflows/python.yml
-        "Programming Language :: Python :: 3.9",
         "Programming Language :: Python :: 3.10",
         "Programming Language :: Python :: 3.11",
         "Programming Language :: Python :: 3.12",
@@ -64,7 +63,9 @@ setuptools.setup(
     },
     # >=3.6 variable type hints, f-strings & * to force keyword-only arguments
     # >=3.8 importlib.metadata
-    python_requires=">=3.9",  # <3.9 untested
+    # >=3.9 type hints dict[…], list[…] & tuple[…] (PEP585)
+    # >=3.10 union types as X | Y (PEP604)
+    python_requires=">=3.10",
     # > Currently, the only main loop supported by dbus-python is GLib.
     # https://web.archive.org/web/20241228081405/https://dbus.freedesktop.org/doc/dbus-python/tutorial.html#setting-up-an-event-loop
     # PyGObject depends on pycairo

+ 10 - 10
systemctl_mqtt/__init__.py

@@ -63,8 +63,8 @@ class _State:
         homeassistant_discovery_prefix: str,
         homeassistant_discovery_object_id: str,
         poweroff_delay: datetime.timedelta,
-        monitored_system_unit_names: typing.List[str],
-        controlled_system_unit_names: typing.List[str],
+        monitored_system_unit_names: list[str],
+        controlled_system_unit_names: list[str],
     ) -> None:
         self._mqtt_topic_prefix = mqtt_topic_prefix
         self._homeassistant_discovery_prefix = homeassistant_discovery_prefix
@@ -72,7 +72,7 @@ class _State:
         self._login_manager = (
             systemctl_mqtt._dbus.login_manager.get_login_manager_proxy()
         )
-        self._shutdown_lock: typing.Optional[jeepney.fds.FileDescriptor] = None
+        self._shutdown_lock: jeepney.fds.FileDescriptor | None = None
         self._shutdown_lock_mutex = threading.Lock()
         self.poweroff_delay = poweroff_delay
         self._monitored_system_unit_names = monitored_system_unit_names
@@ -103,11 +103,11 @@ class _State:
         return self._mqtt_topic_prefix + "/unit/system/" + unit_name + "/restart"
 
     @property
-    def monitored_system_unit_names(self) -> typing.List[str]:
+    def monitored_system_unit_names(self) -> list[str]:
         return self._monitored_system_unit_names
 
     @property
-    def controlled_system_unit_names(self) -> typing.List[str]:
+    def controlled_system_unit_names(self) -> list[str]:
         return self._controlled_system_unit_names
 
     @property
@@ -338,7 +338,7 @@ _MQTT_TOPIC_SUFFIX_ACTION_MAPPING = {
 
 
 async def _mqtt_message_loop(*, state: _State, mqtt_client: aiomqtt.Client) -> None:
-    action_by_topic: typing.Dict[str, _MQTTAction] = {}
+    action_by_topic: dict[str, _MQTTAction] = {}
     for topic_suffix, action in _MQTT_TOPIC_SUFFIX_ACTION_MAPPING.items():
         topic = state.mqtt_topic_prefix + "/" + topic_suffix
         _LOGGER.info("subscribing to %s", topic)
@@ -496,14 +496,14 @@ async def _run(  # pylint: disable=too-many-arguments
     *,
     mqtt_host: str,
     mqtt_port: int,
-    mqtt_username: typing.Optional[str],
-    mqtt_password: typing.Optional[str],
+    mqtt_username: str | None,
+    mqtt_password: str | None,
     mqtt_topic_prefix: str,
     homeassistant_discovery_prefix: str,
     homeassistant_discovery_object_id: str,
     poweroff_delay: datetime.timedelta,
-    monitored_system_unit_names: typing.List[str],
-    controlled_system_unit_names: typing.List[str],
+    monitored_system_unit_names: list[str],
+    controlled_system_unit_names: list[str],
     mqtt_disable_tls: bool = False,
 ) -> None:
     state = _State(

+ 1 - 2
systemctl_mqtt/_dbus/login_manager.py

@@ -19,7 +19,6 @@ import datetime
 import getpass
 import json
 import logging
-import typing
 
 import jeepney
 import jeepney.io.blocking
@@ -32,7 +31,7 @@ _LOGIN_MANAGER_OBJECT_PATH = "/org/freedesktop/login1"
 _LOGIN_MANAGER_INTERFACE = "org.freedesktop.login1.Manager"
 
 
-def _get_username() -> typing.Optional[str]:
+def _get_username() -> str | None:
     try:
         return getpass.getuser()
     except OSError:

+ 3 - 3
tests/dbus/message-generators/test_login_manager.py

@@ -62,9 +62,9 @@ def mock_open_dbus_connection() -> typing.Iterator[unittest.mock.MagicMock]:
 )
 def test_method(
     member: str,
-    signature: typing.Optional[str],
-    kwargs: typing.Dict[str, typing.Any],
-    body: typing.Tuple[typing.Any],
+    signature: str | None,
+    kwargs: dict[str, typing.Any],
+    body: tuple[typing.Any],
 ) -> None:
     with mock_open_dbus_connection() as dbus_connection_mock:
         proxy = systemctl_mqtt._dbus.login_manager.get_login_manager_proxy()

+ 2 - 3
tests/test_cli.py

@@ -17,7 +17,6 @@
 
 import datetime
 import logging
-import typing
 import unittest.mock
 
 import pytest
@@ -40,7 +39,7 @@ import systemctl_mqtt._utils
         (["--log-level", "critical"], logging.CRITICAL),
     ],
 )
-def test__main_log_level(args: typing.List[str], log_level: int) -> None:
+def test__main_log_level(args: list[str], log_level: int) -> None:
     with unittest.mock.patch("systemctl_mqtt._run") as run_mock, unittest.mock.patch(
         "sys.argv", ["", "--mqtt-host", "mqtt-broker.local"] + args
     ):
@@ -162,7 +161,7 @@ def test__main(
     expected_mqtt_disable_tls,
     expected_username,
     expected_password,
-    expected_topic_prefix: typing.Optional[str],
+    expected_topic_prefix: str | None,
 ):
     # pylint: disable=too-many-arguments
     with unittest.mock.patch("systemctl_mqtt._run") as run_mock, unittest.mock.patch(

+ 1 - 1
tests/test_dbus.py

@@ -316,7 +316,7 @@ async def _get_unit_path_mock(  # pylint: disable=unused-argument
 @pytest.mark.parametrize(
     "monitored_system_unit_names", [[], ["foo.service", "bar.service"]]
 )
-async def test__dbus_signal_loop(monitored_system_unit_names: typing.List[str]) -> None:
+async def test__dbus_signal_loop(monitored_system_unit_names: list[str]) -> None:
     # pylint: disable=too-many-locals,too-many-arguments
     state_mock = unittest.mock.AsyncMock()
     with unittest.mock.patch(

+ 2 - 2
tests/test_state_dbus.py

@@ -174,8 +174,8 @@ async def test_publish_homeassistant_device_config(
     discovery_prefix: str,
     object_id: str,
     hostname: str,
-    monitored_system_unit_names: typing.List[str],
-    controlled_system_unit_names: typing.List[str],
+    monitored_system_unit_names: list[str],
+    controlled_system_unit_names: list[str],
 ) -> None:
     with unittest.mock.patch("jeepney.io.blocking.open_dbus_connection"):
         state = systemctl_mqtt._State(