From 1b52e5bda6f5dc90ad86ca229639f671720d5bb3 Mon Sep 17 00:00:00 2001 From: David Lechner Date: Thu, 7 Aug 2025 16:55:48 -0500 Subject: [PATCH 1/4] pybricksdev: use explicit text encoding for text files Ensure that text files are opened with UTF-8 encoding by default to avoid issues with different default encodings. This also requires updating some dependencies that also had issues with text encoding. PYTHONWARNDEFAULTENCODING is set for tests to try to catch any future issues with text encoding. And PYTHONDEVMODE is set for good measure. --- .github/workflows/test.yml | 3 + CHANGELOG.md | 1 + poetry.lock | 152 ++++++++++++++++++++++------ pybricksdev/cli/__init__.py | 8 +- pybricksdev/cli/flash.py | 2 +- pybricksdev/compile.py | 4 +- pybricksdev/connections/pybricks.py | 2 +- pyproject.toml | 11 +- tests/connections/test_pybricks.py | 20 +++- tests/test_cli.py | 18 ++-- tests/test_compile.py | 4 +- 11 files changed, 172 insertions(+), 53 deletions(-) diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml index 95fb558..e2eae78 100644 --- a/.github/workflows/test.yml +++ b/.github/workflows/test.yml @@ -38,6 +38,9 @@ jobs: - run: poetry install --only=main --only=test - run: poetry run pytest if: matrix.python-version != '3.10' + env: + PYTHONDEVMODE: 1 + PYTHONWARNDEFAULTENCODING: 1 - run: poetry run coverage run if: matrix.python-version == '3.10' - run: poetry run coverage xml diff --git a/CHANGELOG.md b/CHANGELOG.md index bf34ee2..2d51653 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -11,6 +11,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 ### Fixed - Fixed calling `PybricksHub.write()` methods. +- Fixed using default text encoding when opening text files. ### Changed - Downloading programs without starting them can now be done by diff --git a/poetry.lock b/poetry.lock index 92af02d..44fae13 100644 --- a/poetry.lock +++ b/poetry.lock @@ -1,4 +1,4 @@ -# This file is automatically @generated by Poetry 1.8.3 and should not be changed by hand. +# This file is automatically @generated by Poetry 2.1.4 and should not be changed by hand. [[package]] name = "alabaster" @@ -6,6 +6,7 @@ version = "1.0.0" description = "A light, configurable Sphinx theme" optional = false python-versions = ">=3.10" +groups = ["docs"] files = [ {file = "alabaster-1.0.0-py3-none-any.whl", hash = "sha256:fc6786402dc3fcb2de3cabd5fe455a2db534b371124f1f21de8731783dec828b"}, {file = "alabaster-1.0.0.tar.gz", hash = "sha256:c00dca57bca26fa62a6d7d0a9fcce65f3e026e9bfe33e9c538fd3fbb2144fd9e"}, @@ -17,6 +18,7 @@ version = "1.4.4" description = "A small Python module for determining appropriate platform-specific dirs, e.g. a \"user data dir\"." optional = false python-versions = "*" +groups = ["main"] files = [ {file = "appdirs-1.4.4-py2.py3-none-any.whl", hash = "sha256:a841dacd6b99318a741b166adb07e19ee71a274450e68237b4650ca1055ab128"}, {file = "appdirs-1.4.4.tar.gz", hash = "sha256:7d5d0167b2b1ba821647616af46a749d1c653740dd0d2415100fe26e27afdf41"}, @@ -28,6 +30,7 @@ version = "3.6.2" description = "Bash tab completion for argparse" optional = false python-versions = ">=3.8" +groups = ["main"] files = [ {file = "argcomplete-3.6.2-py3-none-any.whl", hash = "sha256:65b3133a29ad53fb42c48cf5114752c7ab66c1c38544fdf6460f450c09b42591"}, {file = "argcomplete-3.6.2.tar.gz", hash = "sha256:d0519b1bc867f5f4f4713c41ad0aba73a4a5f007449716b16f385f2166dc6adf"}, @@ -42,6 +45,8 @@ version = "5.0.1" description = "Timeout context manager for asyncio programs" optional = false python-versions = ">=3.8" +groups = ["main"] +markers = "python_version == \"3.10\"" files = [ {file = "async_timeout-5.0.1-py3-none-any.whl", hash = "sha256:39e3809566ff85354557ec2398b55e096c8364bacac9405a7a1fa429e77fe76c"}, {file = "async_timeout-5.0.1.tar.gz", hash = "sha256:d9321a7a3d5a6a5e187e824d2fa0793ce379a202935782d555d6e9d2735677d3"}, @@ -53,13 +58,14 @@ version = "2.17.0" description = "Internationalization utilities" optional = false python-versions = ">=3.8" +groups = ["docs"] files = [ {file = "babel-2.17.0-py3-none-any.whl", hash = "sha256:4d0b53093fdfb4b21c92b5213dba5a1b23885afa8383709427046b21c366e5f2"}, {file = "babel-2.17.0.tar.gz", hash = "sha256:0c54cffb19f690cdcc52a3b50bcbf71e07a808d1c80d549f2459b9d2cf0afb9d"}, ] [package.extras] -dev = ["backports.zoneinfo", "freezegun (>=1.0,<2.0)", "jinja2 (>=3.0)", "pytest (>=6.0)", "pytest-cov", "pytz", "setuptools", "tzdata"] +dev = ["backports.zoneinfo ; python_version < \"3.9\"", "freezegun (>=1.0,<2.0)", "jinja2 (>=3.0)", "pytest (>=6.0)", "pytest-cov", "pytz", "setuptools", "tzdata ; sys_platform == \"win32\""] [[package]] name = "backports-asyncio-runner" @@ -67,6 +73,8 @@ version = "1.2.0" description = "Backport of asyncio.Runner, a context manager that controls event loop life cycle." optional = false python-versions = "<3.11,>=3.8" +groups = ["test"] +markers = "python_version == \"3.10\"" files = [ {file = "backports_asyncio_runner-1.2.0-py3-none-any.whl", hash = "sha256:0da0a936a8aeb554eccb426dc55af3ba63bcdc69fa1a600b5bb305413a4477b5"}, {file = "backports_asyncio_runner-1.2.0.tar.gz", hash = "sha256:a5aa7b2b7d8f8bfcaa2b57313f70792df84e32a2a746f585213373f900b42162"}, @@ -78,6 +86,7 @@ version = "24.10.0" description = "The uncompromising code formatter." optional = false python-versions = ">=3.9" +groups = ["lint"] files = [ {file = "black-24.10.0-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:e6668650ea4b685440857138e5fe40cde4d652633b1bdffc62933d0db4ed9812"}, {file = "black-24.10.0-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:1c536fcf674217e87b8cc3657b81809d3c085d7bf3ef262ead700da345bfa6ea"}, @@ -124,6 +133,7 @@ version = "1.0.1" description = "Bluetooth Low Energy platform Agnostic Klient" optional = false python-versions = ">=3.9" +groups = ["main"] files = [ {file = "bleak-1.0.1-py3-none-any.whl", hash = "sha256:8f99bcb2fb74950466622b1f932ab661c74dcd48a3d122e95b661aa0705e5a6a"}, {file = "bleak-1.0.1.tar.gz", hash = "sha256:6177487c4eb08743a155e1295ff871eb2a61669b538bdbf35db45ea29cf7a41d"}, @@ -151,6 +161,7 @@ version = "2025.8.3" description = "Python package for providing Mozilla's CA Bundle." optional = false python-versions = ">=3.7" +groups = ["docs"] files = [ {file = "certifi-2025.8.3-py3-none-any.whl", hash = "sha256:f6c12493cfb1b06ba2ff328595af9350c65d6644968e5d3a2ffd78699af217a5"}, {file = "certifi-2025.8.3.tar.gz", hash = "sha256:e564105f78ded564e3ae7c923924435e1daa7463faeab5bb932bc53ffae63407"}, @@ -162,6 +173,7 @@ version = "3.4.2" description = "The Real First Universal Charset Detector. Open, modern and actively maintained alternative to Chardet." optional = false python-versions = ">=3.7" +groups = ["docs"] files = [ {file = "charset_normalizer-3.4.2-cp310-cp310-macosx_10_9_universal2.whl", hash = "sha256:7c48ed483eb946e6c04ccbe02c6b4d1d48e51944b6db70f697e089c193404941"}, {file = "charset_normalizer-3.4.2-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:b2d318c11350e10662026ad0eb71bb51c7812fc8590825304ae0bdd4ac283acd"}, @@ -263,6 +275,7 @@ version = "8.2.1" description = "Composable command line interface toolkit" optional = false python-versions = ">=3.10" +groups = ["lint"] files = [ {file = "click-8.2.1-py3-none-any.whl", hash = "sha256:61a3265b914e850b85317d0b3109c7f8cd35a670f963866005d6ef1d5175a12b"}, {file = "click-8.2.1.tar.gz", hash = "sha256:27c491cc05d968d271d5a1db13e3b5a184636d9d930f148c50b038f0d0646202"}, @@ -277,10 +290,12 @@ version = "0.4.6" description = "Cross-platform colored terminal text." optional = false python-versions = "!=3.0.*,!=3.1.*,!=3.2.*,!=3.3.*,!=3.4.*,!=3.5.*,!=3.6.*,>=2.7" +groups = ["main", "docs", "lint", "test"] files = [ {file = "colorama-0.4.6-py2.py3-none-any.whl", hash = "sha256:4f1d9991f5acc0ca119f9d443620b77f9d6b33703e51011c16baf57afb285fc6"}, {file = "colorama-0.4.6.tar.gz", hash = "sha256:08695f5cb7ed6e0531a20572697297273c47b8cae5a63ffc6d6ed5c201be6e44"}, ] +markers = {main = "platform_system == \"Windows\"", docs = "sys_platform == \"win32\"", lint = "platform_system == \"Windows\"", test = "sys_platform == \"win32\""} [[package]] name = "coverage" @@ -288,6 +303,7 @@ version = "7.10.2" description = "Code coverage measurement for Python" optional = false python-versions = ">=3.9" +groups = ["test"] files = [ {file = "coverage-7.10.2-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:79f0283ab5e6499fd5fe382ca3d62afa40fb50ff227676a3125d18af70eabf65"}, {file = "coverage-7.10.2-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:e4545e906f595ee8ab8e03e21be20d899bfc06647925bc5b224ad7e8c40e08b8"}, @@ -383,7 +399,7 @@ files = [ tomli = {version = "*", optional = true, markers = "python_full_version <= \"3.11.0a6\" and extra == \"toml\""} [package.extras] -toml = ["tomli"] +toml = ["tomli ; python_full_version <= \"3.11.0a6\""] [[package]] name = "dbus-fast" @@ -391,6 +407,8 @@ version = "2.44.3" description = "A faster version of dbus-next" optional = false python-versions = ">=3.9" +groups = ["main"] +markers = "platform_system == \"Linux\"" files = [ {file = "dbus_fast-2.44.3-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:644880d8db53a6d92e88015f6ac6e0d9a5c1bfdacbc5356de816212cca33c629"}, {file = "dbus_fast-2.44.3-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:be7e2e39bc6a5e0fe758d9d7abb19f91a7540e3b45124764f318147b74c9b2e6"}, @@ -445,6 +463,7 @@ version = "0.21.2" description = "Docutils -- Python Documentation Utilities" optional = false python-versions = ">=3.9" +groups = ["docs"] files = [ {file = "docutils-0.21.2-py3-none-any.whl", hash = "sha256:dafca5b9e384f0e419294eb4d2ff9fa826435bf15f15b7bd45723e8ad76811b2"}, {file = "docutils-0.21.2.tar.gz", hash = "sha256:3a6b18732edf182daa3cd12775bbb338cf5691468f91eeeb109deff6ebfa986f"}, @@ -456,6 +475,8 @@ version = "1.3.0" description = "Backport of PEP 654 (exception groups)" optional = false python-versions = ">=3.7" +groups = ["test"] +markers = "python_version == \"3.10\"" files = [ {file = "exceptiongroup-1.3.0-py3-none-any.whl", hash = "sha256:4d111e6e0c13d0644cad6ddaa7ed0261a0b36971f6d23e7ec9b4b9097da78a10"}, {file = "exceptiongroup-1.3.0.tar.gz", hash = "sha256:b241f5885f560bc56a59ee63ca4c6a8bfa46ae4ad651af316d4e81817bb9fd88"}, @@ -473,6 +494,7 @@ version = "7.3.0" description = "the modular source code checker: pep8 pyflakes and co" optional = false python-versions = ">=3.9" +groups = ["lint"] files = [ {file = "flake8-7.3.0-py2.py3-none-any.whl", hash = "sha256:b9696257b9ce8beb888cdbe31cf885c90d31928fe202be0889a7cdafad32f01e"}, {file = "flake8-7.3.0.tar.gz", hash = "sha256:fe044858146b9fc69b551a4b490d69cf960fcb78ad1edcb84e7fbb1b4a8e3872"}, @@ -489,6 +511,7 @@ version = "0.14.0.post4" description = "A Cython interface to the hidapi from https://github.com/libusb/hidapi" optional = false python-versions = "*" +groups = ["main"] files = [ {file = "hidapi-0.14.0.post4-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:01747e681d138ec614321ef6f069e5be3743fa210112e529a34d3e99635e4ac0"}, {file = "hidapi-0.14.0.post4-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:8e20d0a1298a4bd342d7d927d928f1a5a29e5fc9dbf9a79e95dc6e2d386d5070"}, @@ -580,6 +603,7 @@ version = "3.10" description = "Internationalized Domain Names in Applications (IDNA)" optional = false python-versions = ">=3.6" +groups = ["docs"] files = [ {file = "idna-3.10-py3-none-any.whl", hash = "sha256:946d195a0d259cbba61165e88e65941f16e9b36ea6ddb97f00452bae8b1287d3"}, {file = "idna-3.10.tar.gz", hash = "sha256:12f65c9b470abda6dc35cf8e63cc574b1c52b11df2c86030af0ac09b01b13ea9"}, @@ -594,6 +618,7 @@ version = "1.4.1" description = "Getting image size from png/jpeg/jpeg2000/gif file" optional = false python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*" +groups = ["docs"] files = [ {file = "imagesize-1.4.1-py2.py3-none-any.whl", hash = "sha256:0d8d18d08f840c19d0ee7ca1fd82490fdc3729b7ac93f49870406ddde8ef8d8b"}, {file = "imagesize-1.4.1.tar.gz", hash = "sha256:69150444affb9cb0d5cc5a92b3676f0b2fb7cd9ae39e947a5e11a36b4497cd4a"}, @@ -605,6 +630,7 @@ version = "2.1.0" description = "brain-dead simple config-ini parsing" optional = false python-versions = ">=3.8" +groups = ["test"] files = [ {file = "iniconfig-2.1.0-py3-none-any.whl", hash = "sha256:9deba5723312380e77435581c6bf4935c94cbfab9b1ed33ef8d238ea168eb760"}, {file = "iniconfig-2.1.0.tar.gz", hash = "sha256:3abbd2e30b36733fee78f9c7f7308f2d0050e88f0087fd25c2645f63c773e1c7"}, @@ -616,6 +642,7 @@ version = "6.0.1" description = "A Python utility / library to sort Python imports." optional = false python-versions = ">=3.9.0" +groups = ["lint"] files = [ {file = "isort-6.0.1-py3-none-any.whl", hash = "sha256:2dc5d7f65c9678d94c88dfc29161a320eec67328bc97aad576874cb4be1e9615"}, {file = "isort-6.0.1.tar.gz", hash = "sha256:1cb5df28dfbc742e490c5e41bad6da41b805b0a8be7bc93cd0fb2a8a890ac450"}, @@ -631,6 +658,7 @@ version = "3.1.6" description = "A very fast and expressive template engine." optional = false python-versions = ">=3.7" +groups = ["docs"] files = [ {file = "jinja2-3.1.6-py3-none-any.whl", hash = "sha256:85ece4451f492d0c13c5dd7c13a64681a86afae63a5f347908daf103ce6d2f67"}, {file = "jinja2-3.1.6.tar.gz", hash = "sha256:0137fb05990d35f1275a587e9aee6d56da821fc83491a0fb838183be43f66d6d"}, @@ -648,6 +676,7 @@ version = "3.0.2" description = "Safely add untrusted strings to HTML/XML markup." optional = false python-versions = ">=3.9" +groups = ["docs"] files = [ {file = "MarkupSafe-3.0.2-cp310-cp310-macosx_10_9_universal2.whl", hash = "sha256:7e94c425039cde14257288fd61dcfb01963e658efbc0ff54f5306b06054700f8"}, {file = "MarkupSafe-3.0.2-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:9e2d922824181480953426608b81967de705c3cef4d1af983af849d7bd619158"}, @@ -718,6 +747,7 @@ version = "0.7.0" description = "McCabe checker, plugin for flake8" optional = false python-versions = ">=3.6" +groups = ["lint"] files = [ {file = "mccabe-0.7.0-py2.py3-none-any.whl", hash = "sha256:6c2d30ab6be0e4a46919781807b4f0d834ebdd6c6e3dca0bda5a15f863427b6e"}, {file = "mccabe-0.7.0.tar.gz", hash = "sha256:348e0240c33b60bbdf4e523192ef919f28cb2c3d7d5c7794f74009290f236325"}, @@ -725,38 +755,42 @@ files = [ [[package]] name = "mpy-cross-v5" -version = "1.0.2" +version = "1.1.0" description = "Python wrapper for the mpy-cross tool from MicroPython." optional = false python-versions = "*" +groups = ["main"] files = [ - {file = "mpy_cross_v5-1.0.2-py3-none-macosx_10_9_x86_64.whl", hash = "sha256:ff39973757c5320f6b8847092c27b6a101d968886f95cc0ae8287cea3589764b"}, - {file = "mpy_cross_v5-1.0.2-py3-none-macosx_11_0_arm64.whl", hash = "sha256:6ffdf89264177ad38dcf91bc35dae4c3f4fc1c1f6db52c39401e23b618319560"}, - {file = "mpy_cross_v5-1.0.2-py3-none-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:8d6de29ffd19c9c0644ff37aa05e983ca560981ce020cbd71c23b55b72b57c02"}, - {file = "mpy_cross_v5-1.0.2-py3-none-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:b53afef10e315dbe85a294d932e9af4638abc95e10d0feeaab44119e25c627d2"}, - {file = "mpy_cross_v5-1.0.2-py3-none-musllinux_1_1_aarch64.whl", hash = "sha256:6fbc3f256726ce01f0621b1b964097dcc6efc9eabb205f413773a3066d5be277"}, - {file = "mpy_cross_v5-1.0.2-py3-none-musllinux_1_1_x86_64.whl", hash = "sha256:a3d9c151318c5c4d298fb477497b15ccb2bcde4f0d7e32a7b02179482429a52e"}, - {file = "mpy_cross_v5-1.0.2-py3-none-win32.whl", hash = "sha256:121c22ba2fef5549ceb0640d046c0606857d83cf93aa1bda8084fee8366aa148"}, - {file = "mpy_cross_v5-1.0.2-py3-none-win_amd64.whl", hash = "sha256:bc003357bdc69912a0affa2bb87cefe531bcdcd21e1646f939a4773d6801b435"}, - {file = "mpy_cross_v5-1.0.2.tar.gz", hash = "sha256:50797bd49e675d262d44816c407f8c8074b4d4304ff9b8dd7aec35f3210b29ce"}, + {file = "mpy_cross_v5-1.1.0-py3-none-macosx_10_13_x86_64.whl", hash = "sha256:74cb3f4285c1ad93448b97ccdae326081981f56a9d0069e49748626542294bd2"}, + {file = "mpy_cross_v5-1.1.0-py3-none-macosx_11_0_arm64.whl", hash = "sha256:20f64df0451c618c338a7bd0a2430f5b750dbc05d9695025fea690159f5908ae"}, + {file = "mpy_cross_v5-1.1.0-py3-none-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:9e93189bd679441158dfbc70235818671b91f18488201365e69cfcefbe85b50e"}, + {file = "mpy_cross_v5-1.1.0-py3-none-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:5357eaf42cd2a2cfa7f764b2dfdcd656e832997c4e464728604f25f2df628aed"}, + {file = "mpy_cross_v5-1.1.0-py3-none-musllinux_1_2_aarch64.whl", hash = "sha256:e3e303f066d29406a6d1138163a373e8da1d08dbfce5d970d630701f59d74977"}, + {file = "mpy_cross_v5-1.1.0-py3-none-musllinux_1_2_x86_64.whl", hash = "sha256:e1158bfb3baf18d6c90491c9d70acd31ff48568269e4b4062634f9d0037a27b9"}, + {file = "mpy_cross_v5-1.1.0-py3-none-win32.whl", hash = "sha256:acaf1b46278c7923f22a357b56f78ae752276afe65d6580c6f6d8ce4700705a1"}, + {file = "mpy_cross_v5-1.1.0-py3-none-win_amd64.whl", hash = "sha256:2ab2141808f1144c14d3da7d9f60532860b578e946ce0ecdf348a3ba201abd11"}, + {file = "mpy_cross_v5-1.1.0-py3-none-win_arm64.whl", hash = "sha256:7f4ffa33edd784780c79931cdf21b40482bf056b6645d21717534b5a7af2596b"}, + {file = "mpy_cross_v5-1.1.0.tar.gz", hash = "sha256:4d6c2611d980b7dd5972380ce4f067c65059500e358e3fbc1662c63496f7933f"}, ] [[package]] name = "mpy-cross-v6" -version = "1.0.2" +version = "1.1.0" description = "Python wrapper for the mpy-cross tool from MicroPython." optional = false python-versions = "*" +groups = ["main"] files = [ - {file = "mpy_cross_v6-1.0.2-py3-none-macosx_10_9_x86_64.whl", hash = "sha256:5de0c37656d70376c15e2258f7d3440a1c7723de5543583c8c862b615963c406"}, - {file = "mpy_cross_v6-1.0.2-py3-none-macosx_11_0_arm64.whl", hash = "sha256:d4d3d041efbc7152613f57e79e6dab3951195a138fb0955a5bc10b35cd9a5076"}, - {file = "mpy_cross_v6-1.0.2-py3-none-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:fc11204a04a62efeaa188e682f9df8106efa5b7ed2e054ffb00e2231b2068ab8"}, - {file = "mpy_cross_v6-1.0.2-py3-none-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:497e0206f35cb2156081ccbb90969dc1a3b379b12b7e873a609de7b4f4ad51f6"}, - {file = "mpy_cross_v6-1.0.2-py3-none-musllinux_1_1_aarch64.whl", hash = "sha256:7e6517335e845ae2d3f433f680854a646caa8f3b24dc8cd7afef1698a61f4773"}, - {file = "mpy_cross_v6-1.0.2-py3-none-musllinux_1_1_x86_64.whl", hash = "sha256:99978e8bf6acb3265da72157559080792bcf4646db3c797546e581972fb13c0d"}, - {file = "mpy_cross_v6-1.0.2-py3-none-win32.whl", hash = "sha256:db7ca32c3c74ee3ca18d9032a7d0fd6f77054f0dc1830fba607b50183721a738"}, - {file = "mpy_cross_v6-1.0.2-py3-none-win_amd64.whl", hash = "sha256:5a63e082d9084e4e51ba023d844dc92ea32f777536e46969895b9fc89011a8db"}, - {file = "mpy_cross_v6-1.0.2.tar.gz", hash = "sha256:8e67d5ddf4fd49274a0eb6efe60a919a90c57925c0b2127154b75f23d18f7f96"}, + {file = "mpy_cross_v6-1.1.0-py3-none-macosx_10_13_x86_64.whl", hash = "sha256:937d04f66e93757607cf88355125551b5cee2e4e0495a84f0776eaaac0a9afa7"}, + {file = "mpy_cross_v6-1.1.0-py3-none-macosx_11_0_arm64.whl", hash = "sha256:cc88c8dfba1b764c45bbba0a7e9193f5b6a5eee16c4433c1e0e68c0fc3963059"}, + {file = "mpy_cross_v6-1.1.0-py3-none-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:fa06072a0ab7081b1182db9a353c3adb1e2498adae18a35ec067213e44b82431"}, + {file = "mpy_cross_v6-1.1.0-py3-none-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:b7c58b85af2e233c27f48aeb2caf289d014b10cb6639ebc439776481383e7942"}, + {file = "mpy_cross_v6-1.1.0-py3-none-musllinux_1_2_aarch64.whl", hash = "sha256:b7cac764fffac8101e554fc680b18962ed3fd21b4119f8c34566ae5dad367c59"}, + {file = "mpy_cross_v6-1.1.0-py3-none-musllinux_1_2_x86_64.whl", hash = "sha256:8fdc34dd3f54ac25a8bc1ac9fe7d54e89537d6c3c66d97d90e8dd1de0c248c2a"}, + {file = "mpy_cross_v6-1.1.0-py3-none-win32.whl", hash = "sha256:0b83270468207a2d387bbecc5c73f4e8c6586ee456a41a188b985c29bbbc9e17"}, + {file = "mpy_cross_v6-1.1.0-py3-none-win_amd64.whl", hash = "sha256:baad0dcc41c67b0831ebdc4bfff5009d118158bb937ec51aca74f51ccebc1861"}, + {file = "mpy_cross_v6-1.1.0-py3-none-win_arm64.whl", hash = "sha256:807711b4b6725edc142f531ed9f08276e0a5fbd7467d365ec0cecd9fc11d6790"}, + {file = "mpy_cross_v6-1.1.0.tar.gz", hash = "sha256:977a0f82bb2570068f875f2ecf63807b55cf0ce10944cd1174ae14fb60ef897f"}, ] [[package]] @@ -765,6 +799,7 @@ version = "1.1.0" description = "Type system extensions for programs checked with the mypy type checker." optional = false python-versions = ">=3.8" +groups = ["lint"] files = [ {file = "mypy_extensions-1.1.0-py3-none-any.whl", hash = "sha256:1be4cccdb0f2482337c4743e60421de3a356cd97508abadd57d47403e94f5505"}, {file = "mypy_extensions-1.1.0.tar.gz", hash = "sha256:52e68efc3284861e772bbcd66823fde5ae21fd2fdb51c62a211403730b916558"}, @@ -776,6 +811,7 @@ version = "25.0" description = "Core utilities for Python packages" optional = false python-versions = ">=3.8" +groups = ["main", "docs", "lint", "test"] files = [ {file = "packaging-25.0-py3-none-any.whl", hash = "sha256:29572ef2b1f17581046b3a2227d5c611fb25ec70ca1ba8554b24b0e69331a484"}, {file = "packaging-25.0.tar.gz", hash = "sha256:d443872c98d677bf60f6a1f2f8c1cb748e8fe762d2bf9d3148b5599295b0fc4f"}, @@ -787,6 +823,7 @@ version = "0.12.1" description = "Utility library for gitignore style pattern matching of file paths." optional = false python-versions = ">=3.8" +groups = ["lint"] files = [ {file = "pathspec-0.12.1-py3-none-any.whl", hash = "sha256:a0d503e138a4c123b27490a4f7beda6a01c6f288df0e4a8b79c7eb0dc7b4cc08"}, {file = "pathspec-0.12.1.tar.gz", hash = "sha256:a482d51503a1ab33b1c67a6c3813a26953dbdc71c31dacaef9a838c4e29f5712"}, @@ -798,6 +835,7 @@ version = "4.3.8" description = "A small Python package for determining appropriate platform-specific dirs, e.g. a `user data dir`." optional = false python-versions = ">=3.9" +groups = ["lint"] files = [ {file = "platformdirs-4.3.8-py3-none-any.whl", hash = "sha256:ff7059bb7eb1179e2685604f4aaf157cfd9535242bd23742eadc3c13542139b4"}, {file = "platformdirs-4.3.8.tar.gz", hash = "sha256:3d512d96e16bcb959a814c9f348431070822a6496326a4be0911c40b5a74c2bc"}, @@ -814,6 +852,7 @@ version = "1.6.0" description = "plugin and hook calling mechanisms for python" optional = false python-versions = ">=3.9" +groups = ["test"] files = [ {file = "pluggy-1.6.0-py3-none-any.whl", hash = "sha256:e920276dd6813095e9377c0bc5566d94c932c33b27a3e3945d8389c374dd4746"}, {file = "pluggy-1.6.0.tar.gz", hash = "sha256:7dcc130b76258d33b90f61b658791dede3486c3e6bfb003ee5c9bfb396dd22f3"}, @@ -829,6 +868,7 @@ version = "3.0.51" description = "Library for building powerful interactive command lines in Python" optional = false python-versions = ">=3.8" +groups = ["main"] files = [ {file = "prompt_toolkit-3.0.51-py3-none-any.whl", hash = "sha256:52742911fde84e2d423e2f9a4cf1de7d7ac4e51958f648d9540e0fb8db077b07"}, {file = "prompt_toolkit-3.0.51.tar.gz", hash = "sha256:931a162e3b27fc90c86f1b48bb1fb2c528c2761475e57c9c06de13311c7b54ed"}, @@ -843,6 +883,7 @@ version = "3.6.1" description = "Documentation and user-API stubs for Pybricks MicroPython" optional = false python-versions = "<4.0,>=3.8" +groups = ["main"] files = [ {file = "pybricks-3.6.1-py3-none-any.whl", hash = "sha256:ff177a4c4728df1ea22cc7ac63c403affd0d1f64cc389a385f5b27561ab08c23"}, {file = "pybricks-3.6.1.tar.gz", hash = "sha256:1836b5e14e143eec02a8c57d4677ab96a223a653e813567df072d90722d9f048"}, @@ -854,6 +895,7 @@ version = "2.14.0" description = "Python style guide checker" optional = false python-versions = ">=3.9" +groups = ["lint"] files = [ {file = "pycodestyle-2.14.0-py2.py3-none-any.whl", hash = "sha256:dd6bf7cb4ee77f8e016f9c8e74a35ddd9f67e1d5fd4184d86c3b98e07099f42d"}, {file = "pycodestyle-2.14.0.tar.gz", hash = "sha256:c4b5b517d278089ff9d0abdec919cd97262a3367449ea1c8b49b91529167b783"}, @@ -865,6 +907,7 @@ version = "3.4.0" description = "passive checker of Python programs" optional = false python-versions = ">=3.9" +groups = ["lint"] files = [ {file = "pyflakes-3.4.0-py2.py3-none-any.whl", hash = "sha256:f742a7dbd0d9cb9ea41e9a24a918996e8170c799fa528688d40dd582c8265f4f"}, {file = "pyflakes-3.4.0.tar.gz", hash = "sha256:b24f96fafb7d2ab0ec5075b7350b3d2d2218eab42003821c06344973d3ea2f58"}, @@ -876,6 +919,7 @@ version = "2.19.2" description = "Pygments is a syntax highlighting package written in Python." optional = false python-versions = ">=3.8" +groups = ["docs", "test"] files = [ {file = "pygments-2.19.2-py3-none-any.whl", hash = "sha256:86540386c03d588bb81d44bc3928634ff26449851e99741617ecb9037ee5ec0b"}, {file = "pygments-2.19.2.tar.gz", hash = "sha256:636cb2477cec7f8952536970bc533bc43743542f70392ae026374600add5b887"}, @@ -890,6 +934,8 @@ version = "11.1" description = "Python<->ObjC Interoperability Module" optional = false python-versions = ">=3.8" +groups = ["main"] +markers = "platform_system == \"Darwin\"" files = [ {file = "pyobjc_core-11.1-cp310-cp310-macosx_10_9_universal2.whl", hash = "sha256:4c7536f3e94de0a3eae6bb382d75f1219280aa867cdf37beef39d9e7d580173c"}, {file = "pyobjc_core-11.1-cp311-cp311-macosx_10_9_universal2.whl", hash = "sha256:ec36680b5c14e2f73d432b03ba7c1457dc6ca70fa59fd7daea1073f2b4157d33"}, @@ -908,6 +954,8 @@ version = "11.1" description = "Wrappers for the Cocoa frameworks on macOS" optional = false python-versions = ">=3.9" +groups = ["main"] +markers = "platform_system == \"Darwin\"" files = [ {file = "pyobjc_framework_cocoa-11.1-cp310-cp310-macosx_10_9_universal2.whl", hash = "sha256:b27a5bdb3ab6cdeb998443ff3fce194ffae5f518c6a079b832dbafc4426937f9"}, {file = "pyobjc_framework_cocoa-11.1-cp311-cp311-macosx_10_9_universal2.whl", hash = "sha256:7b9a9b8ba07f5bf84866399e3de2aa311ed1c34d5d2788a995bdbe82cc36cfa0"}, @@ -929,6 +977,8 @@ version = "11.1" description = "Wrappers for the framework CoreBluetooth on macOS" optional = false python-versions = ">=3.9" +groups = ["main"] +markers = "platform_system == \"Darwin\"" files = [ {file = "pyobjc_framework_corebluetooth-11.1-cp310-cp310-macosx_10_9_universal2.whl", hash = "sha256:ab509994503a5f0ec0f446a7ccc9f9a672d5a427d40dba4563dd00e8e17dfb06"}, {file = "pyobjc_framework_corebluetooth-11.1-cp311-cp311-macosx_10_9_universal2.whl", hash = "sha256:433b8593eb1ea8b6262b243ec903e1de4434b768ce103ebe15aac249b890cc2a"}, @@ -951,6 +1001,8 @@ version = "11.1" description = "Wrappers for libdispatch on macOS" optional = false python-versions = ">=3.9" +groups = ["main"] +markers = "platform_system == \"Darwin\"" files = [ {file = "pyobjc_framework_libdispatch-11.1-cp310-cp310-macosx_10_9_universal2.whl", hash = "sha256:9c598c073a541b5956b5457b94bd33b9ce19ef8d867235439a0fad22d6beab49"}, {file = "pyobjc_framework_libdispatch-11.1-cp311-cp311-macosx_10_9_universal2.whl", hash = "sha256:2ddca472c2cbc6bb192e05b8b501d528ce49333abe7ef0eef28df3133a8e18b7"}, @@ -973,6 +1025,7 @@ version = "8.4.1" description = "pytest: simple powerful testing with Python" optional = false python-versions = ">=3.9" +groups = ["test"] files = [ {file = "pytest-8.4.1-py3-none-any.whl", hash = "sha256:539c70ba6fcead8e78eebbf1115e8b589e7565830d7d006a8723f19ac8a0afb7"}, {file = "pytest-8.4.1.tar.gz", hash = "sha256:7c67fd69174877359ed9371ec3af8a3d2b04741818c51e5e99cc1742251fa93c"}, @@ -996,6 +1049,7 @@ version = "1.1.0" description = "Pytest support for asyncio" optional = false python-versions = ">=3.9" +groups = ["test"] files = [ {file = "pytest_asyncio-1.1.0-py3-none-any.whl", hash = "sha256:5fe2d69607b0bd75c656d1211f969cadba035030156745ee09e7d71740e58ecf"}, {file = "pytest_asyncio-1.1.0.tar.gz", hash = "sha256:796aa822981e01b68c12e4827b8697108f7205020f24b5793b3c41555dab68ea"}, @@ -1015,6 +1069,7 @@ version = "1.3.1" description = "Easy USB access for Python" optional = false python-versions = ">=3.9.0" +groups = ["main"] files = [ {file = "pyusb-1.3.1-py3-none-any.whl", hash = "sha256:bf9b754557af4717fe80c2b07cc2b923a9151f5c08d17bdb5345dac09d6a0430"}, {file = "pyusb-1.3.1.tar.gz", hash = "sha256:3af070b607467c1c164f49d5b0caabe8ac78dbed9298d703a8dbf9df4052d17e"}, @@ -1026,6 +1081,7 @@ version = "4.0.4" description = "ReactiveX (Rx) for Python" optional = false python-versions = ">=3.7,<4.0" +groups = ["main"] files = [ {file = "reactivex-4.0.4-py3-none-any.whl", hash = "sha256:0004796c420bd9e68aad8e65627d85a8e13f293de76656165dffbcb3a0e3fb6a"}, {file = "reactivex-4.0.4.tar.gz", hash = "sha256:e912e6591022ab9176df8348a653fe8c8fa7a301f26f9931c9d8c78a650e04e8"}, @@ -1040,6 +1096,7 @@ version = "2.32.4" description = "Python HTTP for Humans." optional = false python-versions = ">=3.8" +groups = ["docs"] files = [ {file = "requests-2.32.4-py3-none-any.whl", hash = "sha256:27babd3cda2a6d50b30443204ee89830707d396671944c998b5975b031ac2b2c"}, {file = "requests-2.32.4.tar.gz", hash = "sha256:27d0316682c8a29834d3264820024b62a36942083d52caf2f14c0591336d3422"}, @@ -1061,6 +1118,7 @@ version = "3.0.4" description = "Python helper for Semantic Versioning (https://semver.org)" optional = false python-versions = ">=3.7" +groups = ["main"] files = [ {file = "semver-3.0.4-py3-none-any.whl", hash = "sha256:9c824d87ba7f7ab4a1890799cec8596f15c1241cb473404ea1cb0c55e4b04746"}, {file = "semver-3.0.4.tar.gz", hash = "sha256:afc7d8c584a5ed0a11033af086e8af226a9c0b206f313e0301f8dd7b6b589602"}, @@ -1072,19 +1130,20 @@ version = "80.9.0" description = "Easily download, build, install, upgrade, and uninstall Python packages" optional = false python-versions = ">=3.9" +groups = ["main"] files = [ {file = "setuptools-80.9.0-py3-none-any.whl", hash = "sha256:062d34222ad13e0cc312a4c02d73f059e86a4acbfbdea8f8f76b28c99f306922"}, {file = "setuptools-80.9.0.tar.gz", hash = "sha256:f36b47402ecde768dbfafc46e8e4207b4360c654f1f3bb84475f0a28628fb19c"}, ] [package.extras] -check = ["pytest-checkdocs (>=2.4)", "pytest-ruff (>=0.2.1)", "ruff (>=0.8.0)"] -core = ["importlib_metadata (>=6)", "jaraco.functools (>=4)", "jaraco.text (>=3.7)", "more_itertools", "more_itertools (>=8.8)", "packaging (>=24.2)", "platformdirs (>=4.2.2)", "tomli (>=2.0.1)", "wheel (>=0.43.0)"] +check = ["pytest-checkdocs (>=2.4)", "pytest-ruff (>=0.2.1) ; sys_platform != \"cygwin\"", "ruff (>=0.8.0) ; sys_platform != \"cygwin\""] +core = ["importlib_metadata (>=6) ; python_version < \"3.10\"", "jaraco.functools (>=4)", "jaraco.text (>=3.7)", "more_itertools", "more_itertools (>=8.8)", "packaging (>=24.2)", "platformdirs (>=4.2.2)", "tomli (>=2.0.1) ; python_version < \"3.11\"", "wheel (>=0.43.0)"] cover = ["pytest-cov"] doc = ["furo", "jaraco.packaging (>=9.3)", "jaraco.tidelift (>=1.4)", "pygments-github-lexers (==0.0.5)", "pyproject-hooks (!=1.1)", "rst.linker (>=1.9)", "sphinx (>=3.5)", "sphinx-favicon", "sphinx-inline-tabs", "sphinx-lint", "sphinx-notfound-page (>=1,<2)", "sphinx-reredirects", "sphinxcontrib-towncrier", "towncrier (<24.7)"] enabler = ["pytest-enabler (>=2.2)"] -test = ["build[virtualenv] (>=1.0.3)", "filelock (>=3.4.0)", "ini2toml[lite] (>=0.14)", "jaraco.develop (>=7.21)", "jaraco.envs (>=2.2)", "jaraco.path (>=3.7.2)", "jaraco.test (>=5.5)", "packaging (>=24.2)", "pip (>=19.1)", "pyproject-hooks (!=1.1)", "pytest (>=6,!=8.1.*)", "pytest-home (>=0.5)", "pytest-perf", "pytest-subprocess", "pytest-timeout", "pytest-xdist (>=3)", "tomli-w (>=1.0.0)", "virtualenv (>=13.0.0)", "wheel (>=0.44.0)"] -type = ["importlib_metadata (>=7.0.2)", "jaraco.develop (>=7.21)", "mypy (==1.14.*)", "pytest-mypy"] +test = ["build[virtualenv] (>=1.0.3)", "filelock (>=3.4.0)", "ini2toml[lite] (>=0.14)", "jaraco.develop (>=7.21) ; python_version >= \"3.9\" and sys_platform != \"cygwin\"", "jaraco.envs (>=2.2)", "jaraco.path (>=3.7.2)", "jaraco.test (>=5.5)", "packaging (>=24.2)", "pip (>=19.1)", "pyproject-hooks (!=1.1)", "pytest (>=6,!=8.1.*)", "pytest-home (>=0.5)", "pytest-perf ; sys_platform != \"cygwin\"", "pytest-subprocess", "pytest-timeout", "pytest-xdist (>=3)", "tomli-w (>=1.0.0)", "virtualenv (>=13.0.0)", "wheel (>=0.44.0)"] +type = ["importlib_metadata (>=7.0.2) ; python_version < \"3.10\"", "jaraco.develop (>=7.21) ; sys_platform != \"cygwin\"", "mypy (==1.14.*)", "pytest-mypy"] [[package]] name = "snowballstemmer" @@ -1092,6 +1151,7 @@ version = "3.0.1" description = "This package provides 32 stemmers for 30 languages generated from Snowball algorithms." optional = false python-versions = "!=3.0.*,!=3.1.*,!=3.2.*" +groups = ["docs"] files = [ {file = "snowballstemmer-3.0.1-py3-none-any.whl", hash = "sha256:6cd7b3897da8d6c9ffb968a6781fa6532dce9c3618a4b127d920dab764a19064"}, {file = "snowballstemmer-3.0.1.tar.gz", hash = "sha256:6d5eeeec8e9f84d4d56b847692bacf79bc2c8e90c7f80ca4444ff8b6f2e52895"}, @@ -1103,6 +1163,7 @@ version = "8.1.3" description = "Python documentation generator" optional = false python-versions = ">=3.10" +groups = ["docs"] files = [ {file = "sphinx-8.1.3-py3-none-any.whl", hash = "sha256:09719015511837b76bf6e03e42eb7595ac8c2e41eeb9c29c5b755c6b677992a2"}, {file = "sphinx-8.1.3.tar.gz", hash = "sha256:43c1911eecb0d3e161ad78611bc905d1ad0e523e4ddc202a58a821773dc4c927"}, @@ -1138,6 +1199,7 @@ version = "3.0.2" description = "Read the Docs theme for Sphinx" optional = false python-versions = ">=3.8" +groups = ["docs"] files = [ {file = "sphinx_rtd_theme-3.0.2-py2.py3-none-any.whl", hash = "sha256:422ccc750c3a3a311de4ae327e82affdaf59eb695ba4936538552f3b00f4ee13"}, {file = "sphinx_rtd_theme-3.0.2.tar.gz", hash = "sha256:b7457bc25dda723b20b086a670b9953c859eab60a2a03ee8eb2bb23e176e5f85"}, @@ -1157,6 +1219,7 @@ version = "2.0.0" description = "sphinxcontrib-applehelp is a Sphinx extension which outputs Apple help books" optional = false python-versions = ">=3.9" +groups = ["docs"] files = [ {file = "sphinxcontrib_applehelp-2.0.0-py3-none-any.whl", hash = "sha256:4cd3f0ec4ac5dd9c17ec65e9ab272c9b867ea77425228e68ecf08d6b28ddbdb5"}, {file = "sphinxcontrib_applehelp-2.0.0.tar.gz", hash = "sha256:2f29ef331735ce958efa4734873f084941970894c6090408b079c61b2e1c06d1"}, @@ -1173,6 +1236,7 @@ version = "2.0.0" description = "sphinxcontrib-devhelp is a sphinx extension which outputs Devhelp documents" optional = false python-versions = ">=3.9" +groups = ["docs"] files = [ {file = "sphinxcontrib_devhelp-2.0.0-py3-none-any.whl", hash = "sha256:aefb8b83854e4b0998877524d1029fd3e6879210422ee3780459e28a1f03a8a2"}, {file = "sphinxcontrib_devhelp-2.0.0.tar.gz", hash = "sha256:411f5d96d445d1d73bb5d52133377b4248ec79db5c793ce7dbe59e074b4dd1ad"}, @@ -1189,6 +1253,7 @@ version = "2.1.0" description = "sphinxcontrib-htmlhelp is a sphinx extension which renders HTML help files" optional = false python-versions = ">=3.9" +groups = ["docs"] files = [ {file = "sphinxcontrib_htmlhelp-2.1.0-py3-none-any.whl", hash = "sha256:166759820b47002d22914d64a075ce08f4c46818e17cfc9470a9786b759b19f8"}, {file = "sphinxcontrib_htmlhelp-2.1.0.tar.gz", hash = "sha256:c9e2916ace8aad64cc13a0d233ee22317f2b9025b9cf3295249fa985cc7082e9"}, @@ -1205,6 +1270,7 @@ version = "4.1" description = "Extension to include jQuery on newer Sphinx releases" optional = false python-versions = ">=2.7" +groups = ["docs"] files = [ {file = "sphinxcontrib-jquery-4.1.tar.gz", hash = "sha256:1620739f04e36a2c779f1a131a2dfd49b2fd07351bf1968ced074365933abc7a"}, {file = "sphinxcontrib_jquery-4.1-py2.py3-none-any.whl", hash = "sha256:f936030d7d0147dd026a4f2b5a57343d233f1fc7b363f68b3d4f1cb0993878ae"}, @@ -1219,6 +1285,7 @@ version = "1.0.1" description = "A sphinx extension which renders display math in HTML via JavaScript" optional = false python-versions = ">=3.5" +groups = ["docs"] files = [ {file = "sphinxcontrib-jsmath-1.0.1.tar.gz", hash = "sha256:a9925e4a4587247ed2191a22df5f6970656cb8ca2bd6284309578f2153e0c4b8"}, {file = "sphinxcontrib_jsmath-1.0.1-py2.py3-none-any.whl", hash = "sha256:2ec2eaebfb78f3f2078e73666b1415417a116cc848b72e5172e596c871103178"}, @@ -1233,6 +1300,7 @@ version = "2.0.0" description = "sphinxcontrib-qthelp is a sphinx extension which outputs QtHelp documents" optional = false python-versions = ">=3.9" +groups = ["docs"] files = [ {file = "sphinxcontrib_qthelp-2.0.0-py3-none-any.whl", hash = "sha256:b18a828cdba941ccd6ee8445dbe72ffa3ef8cbe7505d8cd1fa0d42d3f2d5f3eb"}, {file = "sphinxcontrib_qthelp-2.0.0.tar.gz", hash = "sha256:4fe7d0ac8fc171045be623aba3e2a8f613f8682731f9153bb2e40ece16b9bbab"}, @@ -1249,6 +1317,7 @@ version = "2.0.0" description = "sphinxcontrib-serializinghtml is a sphinx extension which outputs \"serialized\" HTML files (json and pickle)" optional = false python-versions = ">=3.9" +groups = ["docs"] files = [ {file = "sphinxcontrib_serializinghtml-2.0.0-py3-none-any.whl", hash = "sha256:6e2cb0eef194e10c27ec0023bfeb25badbbb5868244cf5bc5bdc04e4464bf331"}, {file = "sphinxcontrib_serializinghtml-2.0.0.tar.gz", hash = "sha256:e9d912827f872c029017a53f0ef2180b327c3f7fd23c87229f7a8e8b70031d4d"}, @@ -1265,6 +1334,7 @@ version = "0.10.2" description = "Python Library for Tom's Obvious, Minimal Language" optional = false python-versions = ">=2.6, !=3.0.*, !=3.1.*, !=3.2.*" +groups = ["docs"] files = [ {file = "toml-0.10.2-py2.py3-none-any.whl", hash = "sha256:806143ae5bfb6a3c6e736a764057db0e6a0e05e338b5630894a5f779cabb4f9b"}, {file = "toml-0.10.2.tar.gz", hash = "sha256:b3bda1d108d5dd99f4a20d24d9c348e91c4db7ab1b749200bded2f839ccbe68f"}, @@ -1276,6 +1346,7 @@ version = "2.2.1" description = "A lil' TOML parser" optional = false python-versions = ">=3.8" +groups = ["docs", "lint", "test"] files = [ {file = "tomli-2.2.1-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:678e4fa69e4575eb77d103de3df8a895e1591b48e740211bd1067378c69e8249"}, {file = "tomli-2.2.1-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:023aa114dd824ade0100497eb2318602af309e5a55595f76b626d6d9f3b7b0a6"}, @@ -1310,6 +1381,7 @@ files = [ {file = "tomli-2.2.1-py3-none-any.whl", hash = "sha256:cb55c73c5f4408779d0cf3eef9f762b9c9f147a77de7b258bef0a5628adc85cc"}, {file = "tomli-2.2.1.tar.gz", hash = "sha256:cd45e1dc79c835ce60f7404ec8119f2eb06d38b1deba146f07ced3bbc44505ff"}, ] +markers = {docs = "python_version == \"3.10\"", lint = "python_version == \"3.10\"", test = "python_full_version <= \"3.11.0a6\""} [[package]] name = "tqdm" @@ -1317,6 +1389,7 @@ version = "4.67.1" description = "Fast, Extensible Progress Meter" optional = false python-versions = ">=3.7" +groups = ["main"] files = [ {file = "tqdm-4.67.1-py3-none-any.whl", hash = "sha256:26445eca388f82e72884e0d580d5464cd801a3ea01e63e5601bdff9ba6a48de2"}, {file = "tqdm-4.67.1.tar.gz", hash = "sha256:f8aef9c52c08c13a65f30ea34f4e5aac3fd1a34959879d7e59e63027286627f2"}, @@ -1338,6 +1411,7 @@ version = "4.14.1" description = "Backported and Experimental Type Hints for Python 3.9+" optional = false python-versions = ">=3.9" +groups = ["main", "docs", "lint", "test"] files = [ {file = "typing_extensions-4.14.1-py3-none-any.whl", hash = "sha256:d1e1e3b58374dc93031d6eda2420a48ea44a36c2b4766a4fdeb3710755731d76"}, {file = "typing_extensions-4.14.1.tar.gz", hash = "sha256:38b39f4aeeab64884ce9f74c94263ef78f3c22467c8724005483154c26648d36"}, @@ -1349,13 +1423,14 @@ version = "2.5.0" description = "HTTP library with thread-safe connection pooling, file post, and more." optional = false python-versions = ">=3.9" +groups = ["docs"] files = [ {file = "urllib3-2.5.0-py3-none-any.whl", hash = "sha256:e6b01673c0fa6a13e374b50871808eb3bf7046c4b125b216f6bf1cc604cff0dc"}, {file = "urllib3-2.5.0.tar.gz", hash = "sha256:3fc47733c7e419d4bc3f6b3dc2b4f890bb743906a30d56ba4a5bfa4bbff92760"}, ] [package.extras] -brotli = ["brotli (>=1.0.9)", "brotlicffi (>=0.8.0)"] +brotli = ["brotli (>=1.0.9) ; platform_python_implementation == \"CPython\"", "brotlicffi (>=0.8.0) ; platform_python_implementation != \"CPython\""] h2 = ["h2 (>=4,<5)"] socks = ["pysocks (>=1.5.6,!=1.5.7,<2.0)"] zstd = ["zstandard (>=0.18.0)"] @@ -1366,6 +1441,7 @@ version = "0.2.13" description = "Measures the displayed width of unicode strings in a terminal" optional = false python-versions = "*" +groups = ["main"] files = [ {file = "wcwidth-0.2.13-py2.py3-none-any.whl", hash = "sha256:3da69048e4540d84af32131829ff948f1e022c1c6bdb8d6102117aac784f6859"}, {file = "wcwidth-0.2.13.tar.gz", hash = "sha256:72ea0c06399eb286d978fdedb6923a9eb47e1c486ce63e9b4e64fc18303972b5"}, @@ -1377,6 +1453,8 @@ version = "3.2.1" description = "Python projection of Windows Runtime (WinRT) APIs" optional = false python-versions = ">=3.9" +groups = ["main"] +markers = "platform_system == \"Windows\"" files = [ {file = "winrt_runtime-3.2.1-cp310-cp310-win32.whl", hash = "sha256:25a2d1e2b45423742319f7e10fa8ca2e7063f01284b6e85e99d805c4b50bbfb3"}, {file = "winrt_runtime-3.2.1-cp310-cp310-win_amd64.whl", hash = "sha256:dc81d5fb736bf1ddecf743928622253dce4d0aac9a57faad776d7a3834e13257"}, @@ -1405,6 +1483,8 @@ version = "3.2.1" description = "Python projection of Windows Runtime (WinRT) APIs" optional = false python-versions = ">=3.9" +groups = ["main"] +markers = "platform_system == \"Windows\"" files = [ {file = "winrt_windows_devices_bluetooth-3.2.1-cp310-cp310-win32.whl", hash = "sha256:49489351037094a088a08fbdf0f99c94e3299b574edb211f717c4c727770af78"}, {file = "winrt_windows_devices_bluetooth-3.2.1-cp310-cp310-win_amd64.whl", hash = "sha256:20f6a21029034c18ea6a6b6df399671813b071102a0d6d8355bb78cf4f547cdb"}, @@ -1436,6 +1516,8 @@ version = "3.2.1" description = "Python projection of Windows Runtime (WinRT) APIs" optional = false python-versions = ">=3.9" +groups = ["main"] +markers = "platform_system == \"Windows\"" files = [ {file = "winrt_windows_devices_bluetooth_advertisement-3.2.1-cp310-cp310-win32.whl", hash = "sha256:a758c5f81a98cc38347fdfb024ce62720969480e8c5b98e402b89d2b09b32866"}, {file = "winrt_windows_devices_bluetooth_advertisement-3.2.1-cp310-cp310-win_amd64.whl", hash = "sha256:f982ef72e729ddd60cdb975293866e84bb838798828933012a57ee4bf12b0ea1"}, @@ -1467,6 +1549,8 @@ version = "3.2.1" description = "Python projection of Windows Runtime (WinRT) APIs" optional = false python-versions = ">=3.9" +groups = ["main"] +markers = "platform_system == \"Windows\"" files = [ {file = "winrt_windows_devices_bluetooth_genericattributeprofile-3.2.1-cp310-cp310-win32.whl", hash = "sha256:af4914d7b30b49232092cd3b934e3ed6f5d3b1715ba47238541408ee595b7f46"}, {file = "winrt_windows_devices_bluetooth_genericattributeprofile-3.2.1-cp310-cp310-win_amd64.whl", hash = "sha256:0e557dd52fc80392b8bd7c237e1153a50a164b3983838b4ac674551072efc9ed"}, @@ -1498,6 +1582,8 @@ version = "3.2.1" description = "Python projection of Windows Runtime (WinRT) APIs" optional = false python-versions = ">=3.9" +groups = ["main"] +markers = "platform_system == \"Windows\"" files = [ {file = "winrt_windows_devices_enumeration-3.2.1-cp310-cp310-win32.whl", hash = "sha256:40dac777d8f45b41449f3ff1ae70f0d457f1ede53f53962a6e2521b651533db5"}, {file = "winrt_windows_devices_enumeration-3.2.1-cp310-cp310-win_amd64.whl", hash = "sha256:a101ec3e0ad0a0783032fdcd5dc48e7cd68ee034cbde4f903a8c7b391532c71a"}, @@ -1529,6 +1615,8 @@ version = "3.2.1" description = "Python projection of Windows Runtime (WinRT) APIs" optional = false python-versions = ">=3.9" +groups = ["main"] +markers = "platform_system == \"Windows\"" files = [ {file = "winrt_windows_foundation-3.2.1-cp310-cp310-win32.whl", hash = "sha256:677e98165dcbbf7a2367f905bc61090ef2c568b6e465f87cf7276df4734f3b0b"}, {file = "winrt_windows_foundation-3.2.1-cp310-cp310-win_amd64.whl", hash = "sha256:a8f27b4f0fdb73ccc4a3e24bc8010a6607b2bdd722fa799eafce7daa87d19d39"}, @@ -1560,6 +1648,8 @@ version = "3.2.1" description = "Python projection of Windows Runtime (WinRT) APIs" optional = false python-versions = ">=3.9" +groups = ["main"] +markers = "platform_system == \"Windows\"" files = [ {file = "winrt_windows_foundation_collections-3.2.1-cp310-cp310-win32.whl", hash = "sha256:46948484addfc4db981dab35688d4457533ceb54d4954922af41503fddaa8389"}, {file = "winrt_windows_foundation_collections-3.2.1-cp310-cp310-win_amd64.whl", hash = "sha256:899eaa3a93c35bfb1857d649e8dd60c38b978dda7cedd9725fcdbcebba156fd6"}, @@ -1591,6 +1681,8 @@ version = "3.2.1" description = "Python projection of Windows Runtime (WinRT) APIs" optional = false python-versions = ">=3.9" +groups = ["main"] +markers = "platform_system == \"Windows\"" files = [ {file = "winrt_windows_storage_streams-3.2.1-cp310-cp310-win32.whl", hash = "sha256:89bb2d667ebed6861af36ed2710757456e12921ee56347946540320dacf6c003"}, {file = "winrt_windows_storage_streams-3.2.1-cp310-cp310-win_amd64.whl", hash = "sha256:48a78e5dc7d3488eb77e449c278bc6d6ac28abcdda7df298462c4112d7635d00"}, @@ -1617,6 +1709,6 @@ winrt-runtime = ">=3.2.1.0,<3.3.0.0" all = ["winrt-Windows.Foundation.Collections[all] (>=3.2.1.0,<3.3.0.0)", "winrt-Windows.Foundation[all] (>=3.2.1.0,<3.3.0.0)", "winrt-Windows.Storage[all] (>=3.2.1.0,<3.3.0.0)", "winrt-Windows.System[all] (>=3.2.1.0,<3.3.0.0)"] [metadata] -lock-version = "2.0" +lock-version = "2.1" python-versions = ">=3.10,<3.14" -content-hash = "6da054ce6e6b0dc94a164c0c69de5c6a67ce08fe65d95b8ed33cb0ecbdfc94a2" +content-hash = "89e1f9115afdb712e281d2dd9ed6af76269ba3538fec2434781d27cf6b344b11" diff --git a/pybricksdev/cli/__init__.py b/pybricksdev/cli/__init__.py index b772e0e..bdc5feb 100644 --- a/pybricksdev/cli/__init__.py +++ b/pybricksdev/cli/__init__.py @@ -68,7 +68,9 @@ def _get_script_path(file: TextIO) -> ContextManager[PathLike]: @contextlib.contextmanager def temp_context(): try: - with NamedTemporaryFile(suffix=".py", delete=False) as temp: + with NamedTemporaryFile( + suffix=".py", delete=False, encoding="utf-8" + ) as temp: temp.write(file.buffer.read()) yield temp.name @@ -98,7 +100,7 @@ def add_parser(self, subparsers: argparse._SubParsersAction): "file", metavar="", help="path to a MicroPython script or `-` for stdin", - type=argparse.FileType(), + type=argparse.FileType(encoding="utf-8"), ) parser.add_argument( "--abi", @@ -135,7 +137,7 @@ def add_parser(self, subparsers: argparse._SubParsersAction): "file", metavar="", help="path to a MicroPython script or `-` for stdin", - type=argparse.FileType(), + type=argparse.FileType(encoding="utf-8"), ) parser.add_argument( "-n", diff --git a/pybricksdev/cli/flash.py b/pybricksdev/cli/flash.py index c0c2408..0b708a6 100644 --- a/pybricksdev/cli/flash.py +++ b/pybricksdev/cli/flash.py @@ -108,7 +108,7 @@ async def download_and_run(client: BleakClient, script: str, abi: int) -> None: script: The script to be compiled and run. abi: The MPY ABI version. """ - with NamedTemporaryFile("w", suffix=".py") as temp: + with NamedTemporaryFile("w", suffix=".py", encoding="utf-8") as temp: temp.write(script) # file has to be closed so mpy-cross can open it diff --git a/pybricksdev/compile.py b/pybricksdev/compile.py index fba33b0..72816cd 100644 --- a/pybricksdev/compile.py +++ b/pybricksdev/compile.py @@ -55,7 +55,7 @@ async def compile_file( """ # Get version info - with open(os.path.join(proj_dir, proj_path), "r") as f: + with open(os.path.join(proj_dir, proj_path), "r", encoding="utf-8") as f: loop = asyncio.get_running_loop() script = f.read() @@ -188,7 +188,7 @@ def save_script(py_string): py_path = os.path.join(BUILD_DIR, TMP_PY_SCRIPT) # Write Python command to a file. - with open(py_path, "w") as f: + with open(py_path, "w", encoding="utf-8") as f: f.write(py_string) f.write("\n") diff --git a/pybricksdev/connections/pybricks.py b/pybricksdev/connections/pybricks.py index b7091da..78c904e 100644 --- a/pybricksdev/connections/pybricks.py +++ b/pybricksdev/connections/pybricks.py @@ -194,7 +194,7 @@ def _line_handler(self, line: bytes) -> None: os.makedirs(dir_path) logger.info("Saving log to {0}.".format(full_path)) - self.log_file = open(full_path, "w") + self.log_file = open(full_path, "w", encoding="utf-8") return # The line tells us to close a log file, so do it. diff --git a/pyproject.toml b/pyproject.toml index b7c8629..0f60923 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -28,16 +28,16 @@ include = [ pybricksdev = 'pybricksdev.cli:main' [tool.poetry.dependencies] -argcomplete = ">=1.11.1" +argcomplete = ">=3.6.2" bleak = ">=0.22.0" -mpy-cross-v5 = ">=1.0.0" +mpy-cross-v5 = ">=1.1.0" python = ">=3.10,<3.14" tqdm = ">=4.62.3" pyusb = ">=1.0.2" semver = ">=2.13.0" appdirs = ">=1.4.4" prompt-toolkit = ">=3.0.18" -mpy-cross-v6 = ">=1.0.0" +mpy-cross-v6 = ">=1.1.0" packaging = ">=22" typing-extensions = ">=4.3.0" reactivex = ">=4.0.4" @@ -74,6 +74,11 @@ known_third_party = ["usb"] [tool.pytest.ini_options] asyncio_mode = "strict" +filterwarnings = [ + "error", + # Known issue with reactivex package + "ignore::DeprecationWarning:reactivex.internal", +] [tool.coverage.run] branch = true diff --git a/tests/connections/test_pybricks.py b/tests/connections/test_pybricks.py index bf4a391..482248c 100644 --- a/tests/connections/test_pybricks.py +++ b/tests/connections/test_pybricks.py @@ -37,7 +37,9 @@ async def test_download_modern_protocol(self): with contextlib.ExitStack() as stack: # Create and manage temporary file temp = stack.enter_context( - tempfile.NamedTemporaryFile(suffix=".py", mode="w+", delete=False) + tempfile.NamedTemporaryFile( + suffix=".py", mode="w+", delete=False, encoding="utf-8" + ) ) temp.write("print('test')") temp_path = temp.name @@ -62,7 +64,9 @@ async def test_download_legacy_firmware(self): with contextlib.ExitStack() as stack: # Create and manage temporary file temp = stack.enter_context( - tempfile.NamedTemporaryFile(suffix=".py", mode="w+", delete=False) + tempfile.NamedTemporaryFile( + suffix=".py", mode="w+", delete=False, encoding="utf-8" + ) ) temp.write("print('test')") temp_path = temp.name @@ -86,7 +90,9 @@ async def test_download_unsupported_capabilities(self): with contextlib.ExitStack() as stack: # Create and manage temporary file temp = stack.enter_context( - tempfile.NamedTemporaryFile(suffix=".py", mode="w+", delete=False) + tempfile.NamedTemporaryFile( + suffix=".py", mode="w+", delete=False, encoding="utf-8" + ) ) temp.write("print('test')") temp_path = temp.name @@ -114,7 +120,9 @@ async def test_download_compile_error(self): with contextlib.ExitStack() as stack: # Create and manage temporary file temp = stack.enter_context( - tempfile.NamedTemporaryFile(suffix=".py", mode="w+", delete=False) + tempfile.NamedTemporaryFile( + suffix=".py", mode="w+", delete=False, encoding="utf-8" + ) ) temp.write("print('test' # Missing closing parenthesis") temp_path = temp.name @@ -157,7 +165,9 @@ async def test_run_modern_protocol(self): with contextlib.ExitStack() as stack: # Create and manage temporary file temp = stack.enter_context( - tempfile.NamedTemporaryFile(suffix=".py", mode="w+", delete=False) + tempfile.NamedTemporaryFile( + suffix=".py", mode="w+", delete=False, encoding="utf-8" + ) ) temp.write("print('test')") temp_path = temp.name diff --git a/tests/test_cli.py b/tests/test_cli.py index 679f886..5442727 100644 --- a/tests/test_cli.py +++ b/tests/test_cli.py @@ -71,7 +71,9 @@ async def test_download_ble(self): with contextlib.ExitStack() as stack: # Create and manage temporary file temp = stack.enter_context( - tempfile.NamedTemporaryFile(suffix=".py", mode="w+", delete=False) + tempfile.NamedTemporaryFile( + suffix=".py", mode="w+", delete=False, encoding="utf-8" + ) ) temp.write("print('test')") temp_path = temp.name @@ -80,7 +82,7 @@ async def test_download_ble(self): # Create args args = argparse.Namespace( conntype="ble", - file=open(temp_path, "r"), + file=open(temp_path, "r", encoding="utf-8"), name="MyHub", start=False, wait=False, @@ -118,7 +120,9 @@ async def test_download_usb(self): with contextlib.ExitStack() as stack: # Create and manage temporary file temp = stack.enter_context( - tempfile.NamedTemporaryFile(suffix=".py", mode="w+", delete=False) + tempfile.NamedTemporaryFile( + suffix=".py", mode="w+", delete=False, encoding="utf-8" + ) ) temp.write("print('test')") temp_path = temp.name @@ -127,7 +131,7 @@ async def test_download_usb(self): # Create args args = argparse.Namespace( conntype="usb", - file=open(temp_path, "r"), + file=open(temp_path, "r", encoding="utf-8"), name=None, start=False, wait=False, @@ -208,7 +212,9 @@ async def test_download_connection_error(self): with contextlib.ExitStack() as stack: # Create and manage temporary file temp = stack.enter_context( - tempfile.NamedTemporaryFile(suffix=".py", mode="w+", delete=False) + tempfile.NamedTemporaryFile( + suffix=".py", mode="w+", delete=False, encoding="utf-8" + ) ) temp.write("print('test')") temp_path = temp.name @@ -217,7 +223,7 @@ async def test_download_connection_error(self): # Create args args = argparse.Namespace( conntype="ble", - file=open(temp_path, "r"), + file=open(temp_path, "r", encoding="utf-8"), name="MyHub", start=False, wait=False, diff --git a/tests/test_compile.py b/tests/test_compile.py index 545ec17..6cefcba 100644 --- a/tests/test_compile.py +++ b/tests/test_compile.py @@ -14,7 +14,7 @@ @pytest.mark.parametrize("abi", [5, 6]) @pytest.mark.asyncio async def test_compile_file(abi: int): - with NamedTemporaryFile("w", delete=False) as f: + with NamedTemporaryFile("w", delete=False, encoding="utf-8") as f: try: f.write("print('test')") f.close() @@ -35,7 +35,7 @@ async def test_compile_file(abi: int): @pytest.mark.asyncio async def test_compile_file_invalid_abi(): - with NamedTemporaryFile("w", delete=False) as f: + with NamedTemporaryFile("w", delete=False, encoding="utf-8") as f: try: f.write("print('test')") f.close() From ed81ccb3802550483308705a6294ad72a77a60a4 Mon Sep 17 00:00:00 2001 From: David Lechner Date: Thu, 7 Aug 2025 17:18:51 -0500 Subject: [PATCH 2/4] tests/test_cli: fix leaking file descriptor Ensure opened file is closed before the test ends. --- tests/test_cli.py | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/tests/test_cli.py b/tests/test_cli.py index 5442727..cdb59b0 100644 --- a/tests/test_cli.py +++ b/tests/test_cli.py @@ -82,7 +82,7 @@ async def test_download_ble(self): # Create args args = argparse.Namespace( conntype="ble", - file=open(temp_path, "r", encoding="utf-8"), + file=stack.enter_context(open(temp_path, "r", encoding="utf-8")), name="MyHub", start=False, wait=False, @@ -131,7 +131,7 @@ async def test_download_usb(self): # Create args args = argparse.Namespace( conntype="usb", - file=open(temp_path, "r", encoding="utf-8"), + file=stack.enter_context(open(temp_path, "r", encoding="utf-8")), name=None, start=False, wait=False, @@ -223,7 +223,7 @@ async def test_download_connection_error(self): # Create args args = argparse.Namespace( conntype="ble", - file=open(temp_path, "r", encoding="utf-8"), + file=stack.enter_context(open(temp_path, "r", encoding="utf-8")), name="MyHub", start=False, wait=False, From 0dba23302e950de4396325004ea35a7233a1d703 Mon Sep 17 00:00:00 2001 From: David Lechner Date: Thu, 7 Aug 2025 17:49:30 -0500 Subject: [PATCH 3/4] pyproject: use standard [project] table Move from poetry-specific [tool.poetry] table to the standard [project] table. This fixes warnings from `poetry check`. Link: https://packaging.python.org/en/latest/specifications/pyproject-toml/#declaring-project-metadata-the-project-table --- docs/conf.py | 6 +++--- poetry.lock | 6 ++++-- pyproject.toml | 41 +++++++++++++++++++++++------------------ 3 files changed, 30 insertions(+), 23 deletions(-) diff --git a/docs/conf.py b/docs/conf.py index 13d1d86..133c01b 100644 --- a/docs/conf.py +++ b/docs/conf.py @@ -27,10 +27,10 @@ # -- Project information ----------------------------------------------------- -project = _pyproject["tool"]["poetry"]["name"] +project = _pyproject["project"]["name"] copyright = "2021, The Pybricks Authors" -author = _pyproject["tool"]["poetry"]["authors"][0] -release = f"v{_pyproject['tool']['poetry']['version']}" +author = _pyproject["project"]["authors"][0]["name"] +release = f"v{_pyproject['project']['version']}" version = re.match(r"(v\d+\.\d+)", release)[0] diff --git a/poetry.lock b/poetry.lock index 44fae13..2e1d3b1 100644 --- a/poetry.lock +++ b/poetry.lock @@ -884,6 +884,7 @@ description = "Documentation and user-API stubs for Pybricks MicroPython" optional = false python-versions = "<4.0,>=3.8" groups = ["main"] +markers = "python_version < \"4\"" files = [ {file = "pybricks-3.6.1-py3-none-any.whl", hash = "sha256:ff177a4c4728df1ea22cc7ac63c403affd0d1f64cc389a385f5b27561ab08c23"}, {file = "pybricks-3.6.1.tar.gz", hash = "sha256:1836b5e14e143eec02a8c57d4677ab96a223a653e813567df072d90722d9f048"}, @@ -1082,6 +1083,7 @@ description = "ReactiveX (Rx) for Python" optional = false python-versions = ">=3.7,<4.0" groups = ["main"] +markers = "python_version < \"4\"" files = [ {file = "reactivex-4.0.4-py3-none-any.whl", hash = "sha256:0004796c420bd9e68aad8e65627d85a8e13f293de76656165dffbcb3a0e3fb6a"}, {file = "reactivex-4.0.4.tar.gz", hash = "sha256:e912e6591022ab9176df8348a653fe8c8fa7a301f26f9931c9d8c78a650e04e8"}, @@ -1710,5 +1712,5 @@ all = ["winrt-Windows.Foundation.Collections[all] (>=3.2.1.0,<3.3.0.0)", "winrt- [metadata] lock-version = "2.1" -python-versions = ">=3.10,<3.14" -content-hash = "89e1f9115afdb712e281d2dd9ed6af76269ba3538fec2434781d27cf6b344b11" +python-versions = ">=3.10" +content-hash = "07bb1f2eb75c0ddec598e9e7f0d33748fc7fd1b912139ce347c407bf5b499942" diff --git a/pyproject.toml b/pyproject.toml index 0f60923..84eef1f 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -1,37 +1,42 @@ -[tool.poetry] +[project] name = "pybricksdev" version = "1.2.0" description = "Pybricks developer tools" -authors = ["The Pybricks Authors "] -maintainers = ["Laurens Valk ", "David Lechner " ] -license = "MIT" +authors = [{ name = "The Pybricks Authors", email = "dev@pybricks.com" }] +maintainers = [ + { name = "Laurens Valk", email = "laurens@pybricks.com" }, + { name = "David Lechner", email = "david@pybricks.com" } +] +license = { text = "MIT" } readme = "README.md" -homepage = "https://pybricks.com" -repository = "https://github.com/pybricks/pybricksdev" -documentation = "https://docs.pybricks.com/projects/pybricksdev" classifiers = [ - "Development Status :: 3 - Alpha", "Intended Audience :: Developers", "Natural Language :: English", "Operating System :: OS Independent", ] -include = [ - "AUTHORS.md" -] +requires-python = ">=3.10" +dynamic = ["dependencies"] -[tool.poetry.urls] +[project.urls] +homepage = "https://pybricks.com" +repository = "https://github.com/pybricks/pybricksdev" +documentation = "https://docs.pybricks.com/projects/pybricksdev" "Changelog" = "https://github.com/pybricks/pybricksdev/blob/master/CHANGELOG.md" "Support" = "https://github.com/pybricks/support/discussions" "Issues" = "https://github.com/pybricks/support/issues" -[tool.poetry.scripts] +[project.scripts] pybricksdev = 'pybricksdev.cli:main' +[tool.poetry] +include = [ + "AUTHORS.md" +] + [tool.poetry.dependencies] argcomplete = ">=3.6.2" bleak = ">=0.22.0" mpy-cross-v5 = ">=1.1.0" -python = ">=3.10,<3.14" tqdm = ">=4.62.3" pyusb = ">=1.0.2" semver = ">=2.13.0" @@ -40,9 +45,9 @@ prompt-toolkit = ">=3.0.18" mpy-cross-v6 = ">=1.1.0" packaging = ">=22" typing-extensions = ">=4.3.0" -reactivex = ">=4.0.4" +reactivex = {version = ">=4.0.4", python = "<4"} hidapi = ">=0.14.0" -pybricks = {version = ">=3", allow-prereleases = true} +pybricks = {version = ">=3", allow-prereleases = true, python = "<4"} [tool.poetry.group.lint.dependencies] black = ">=23,<25" @@ -61,8 +66,8 @@ pytest = ">=7.3.1" pytest-asyncio = ">=0.21.0" [build-system] -requires = ["poetry>=0.12"] -build-backend = "poetry.masonry.api" +requires = ["poetry-core>=1.0.0"] +build-backend = "poetry.core.masonry.api" [tool.black] target-version = ['py38'] From 53676ab087c08479549f499532b46ef64ccd4134 Mon Sep 17 00:00:00 2001 From: David Lechner Date: Thu, 7 Aug 2025 17:59:05 -0500 Subject: [PATCH 4/4] LICENSE: bump copyright year to 2025 --- LICENSE | 2 +- docs/conf.py | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/LICENSE b/LICENSE index 508e3fd..489d9e8 100644 --- a/LICENSE +++ b/LICENSE @@ -1,6 +1,6 @@ MIT License -Copyright (c) 2018-2023 The Pybricks Authors +Copyright (c) 2018-2025 The Pybricks Authors Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal diff --git a/docs/conf.py b/docs/conf.py index 133c01b..46b4455 100644 --- a/docs/conf.py +++ b/docs/conf.py @@ -28,7 +28,7 @@ # -- Project information ----------------------------------------------------- project = _pyproject["project"]["name"] -copyright = "2021, The Pybricks Authors" +copyright = "2021-2025, The Pybricks Authors" author = _pyproject["project"]["authors"][0]["name"] release = f"v{_pyproject['project']['version']}" version = re.match(r"(v\d+\.\d+)", release)[0]