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/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 13d1d86..46b4455 100644 --- a/docs/conf.py +++ b/docs/conf.py @@ -27,10 +27,10 @@ # -- Project information ----------------------------------------------------- -project = _pyproject["tool"]["poetry"]["name"] -copyright = "2021, The Pybricks Authors" -author = _pyproject["tool"]["poetry"]["authors"][0] -release = f"v{_pyproject['tool']['poetry']['version']}" +project = _pyproject["project"]["name"] +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] diff --git a/poetry.lock b/poetry.lock index 92af02d..2e1d3b1 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,8 @@ version = "3.6.1" 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"}, @@ -854,6 +896,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 +908,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 +920,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 +935,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 +955,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 +978,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 +1002,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 +1026,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 +1050,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 +1070,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 +1082,8 @@ version = "4.0.4" 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"}, @@ -1040,6 +1098,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 +1120,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 +1132,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 +1153,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 +1165,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 +1201,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 +1221,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 +1238,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 +1255,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 +1272,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 +1287,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 +1302,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 +1319,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 +1336,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 +1348,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 +1383,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 +1391,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 +1413,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 +1425,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 +1443,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 +1455,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 +1485,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 +1518,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 +1551,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 +1584,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 +1617,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 +1650,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 +1683,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 +1711,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" -python-versions = ">=3.10,<3.14" -content-hash = "6da054ce6e6b0dc94a164c0c69de5c6a67ce08fe65d95b8ed33cb0ecbdfc94a2" +lock-version = "2.1" +python-versions = ">=3.10" +content-hash = "07bb1f2eb75c0ddec598e9e7f0d33748fc7fd1b912139ce347c407bf5b499942" 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..84eef1f 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -1,48 +1,53 @@ -[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 = ">=1.11.1" +argcomplete = ">=3.6.2" bleak = ">=0.22.0" -mpy-cross-v5 = ">=1.0.0" -python = ">=3.10,<3.14" +mpy-cross-v5 = ">=1.1.0" 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" +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'] @@ -74,6 +79,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..cdb59b0 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=stack.enter_context(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=stack.enter_context(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=stack.enter_context(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()