From 89ae7a3a05cdda45005db29155d6affdb0bae7e9 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Sun, 17 Nov 2024 01:32:58 +0000 Subject: [PATCH 01/14] Bump piped from `094e66d` to `8d5f6d3` Bumps [piped](https://github.com/FasterSpeeding/Piped) from `094e66d` to `8d5f6d3`. - [Release notes](https://github.com/FasterSpeeding/Piped/releases) - [Commits](https://github.com/FasterSpeeding/Piped/compare/094e66ddc94ec6e08802a4ce82b480eb368b9052...8d5f6d3185b78560ad285aeb9ad7c38f7c65c979) --- updated-dependencies: - dependency-name: piped dependency-type: direct:production ... Signed-off-by: dependabot[bot] --- piped | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/piped b/piped index 094e66ddc..8d5f6d318 160000 --- a/piped +++ b/piped @@ -1 +1 @@ -Subproject commit 094e66ddc94ec6e08802a4ce82b480eb368b9052 +Subproject commit 8d5f6d3185b78560ad285aeb9ad7c38f7c65c979 From 45b3664bb71163b62063aa3ccabd37e3d58aeee1 Mon Sep 17 00:00:00 2001 From: Faster Speeding Date: Sun, 17 Nov 2024 01:41:59 +0000 Subject: [PATCH 02/14] Bump min python version --- pyproject.toml | 14 ++++++-------- 1 file changed, 6 insertions(+), 8 deletions(-) diff --git a/pyproject.toml b/pyproject.toml index f72f9afe5..120d0d517 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -6,7 +6,7 @@ build-backend = "flit_core.buildapi" name = "hikari-tanjun" version = "2.17.6" readme = "README.md" -requires-python = ">=3.9.0,<3.14" +requires-python = ">=3.11.0,<3.14" license = {file = "LICENSE"} authors = [ {name = "Faster Speeding", email="lucina@lmbyrne.dev"} ] keywords = ["hikari"] @@ -16,8 +16,6 @@ classifiers = [ "Intended Audience :: Developers", "Natural Language :: English", "Operating System :: OS Independent", - "Programming Language :: Python :: 3.9", - "Programming Language :: Python :: 3.10", "Programming Language :: Python :: 3.11", "Programming Language :: Python :: 3.12", "Programming Language :: Python :: 3.13", @@ -45,7 +43,7 @@ extend-exclude = "^\\/tanjun\\/_internal\\/vendor\\/.*$" include = ".*pyi?$" line-length = 120 skip-magic-trailing-comma = true -target-version = ["py39"] +target-version = ["py311"] [tool.codespell] ignore-regex = "TimeSchedule|Nd" @@ -81,7 +79,7 @@ max-complexity = 20 max-function-length = 100 # Technically this is 120, but black has a policy of "1 or 2 over is fine if it is tidier", so we have to raise this. max-line-length = 130 -min_python_version = "3.9" +min_python_version = "3.11" pep585-activation = "always" show_source = false statistics = false @@ -130,7 +128,7 @@ skip = ["tanjun/_internal/vendor"] [tool.mypy] # some good strict settings -python_version = 3.9 +python_version = "3.11" strict = true warn_unreachable = true @@ -170,7 +168,7 @@ top_level_targets = ["./docs_src", "./examples", "./noxfile.py", "./tanjun", "./ [tool.piped.github_actions.publish] [tool.piped.github_actions.py_test] codeclimate_token = "117363998d7c6b4bab4ac57348026e1089767e142ccca3eb8cc37da6cf4cc8b9" -python_versions = ["3.9", "3.10", "3.11", "3.12", "3.13-dev"] +python_versions = ["3.11", "3.12", "3.13", "3.14-dev"] [tool.piped.github_actions.reformat] [tool.piped.github_actions.release_docs] @@ -188,7 +186,7 @@ exclude = "docs_src" exclude = ["tanjun/_internal/vendor"] include = ["docs_src", "examples", "tanjun", "noxfile.py", "tests"] -pythonVersion = "3.9" +pythonVersion = "3.11" typeCheckingMode = "strict" reportMissingModuleSource = "error" # Is only "warning" on strict mode. From a16e5030f3c528bb1be059e780babec130716784 Mon Sep 17 00:00:00 2001 From: Faster Speeding Date: Sun, 17 Nov 2024 01:43:02 +0000 Subject: [PATCH 03/14] Temp patch --- .github/workflows/resync-piped.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/workflows/resync-piped.yml b/.github/workflows/resync-piped.yml index 42a59f4bc..8506b4cd7 100644 --- a/.github/workflows/resync-piped.yml +++ b/.github/workflows/resync-piped.yml @@ -19,10 +19,10 @@ jobs: with: submodules: "true" - - name: Set up Python 3.9 + - name: Set up Python 3.11 uses: actions/setup-python@0b93645e9fea7318ecaed2b359559ac225c90a2b with: - python-version: "3.9" + python-version: "3.11" - name: install prerequisites run: | From fdf9f1cd9000e8f89c1be992d31a6effea877a3a Mon Sep 17 00:00:00 2001 From: "always-on-duty[bot]" <120557446+always-on-duty[bot]@users.noreply.github.com> Date: Sun, 17 Nov 2024 01:43:33 +0000 Subject: [PATCH 04/14] Resync piped --- .github/workflows/freeze-for-pr.yml | 4 ++-- .github/workflows/lint.yml | 4 ++-- .github/workflows/pr-docs.yml | 4 ++-- .github/workflows/publish.yml | 4 ++-- .github/workflows/py-test.yml | 6 +++--- .github/workflows/reformat.yml | 4 ++-- .github/workflows/release-docs.yml | 4 ++-- .github/workflows/type-check.yml | 4 ++-- .github/workflows/update-licence.yml | 4 ++-- .github/workflows/upgrade-locks.yml | 4 ++-- .github/workflows/verify-locks.yml | 4 ++-- .github/workflows/verify-types.yml | 4 ++-- 12 files changed, 25 insertions(+), 25 deletions(-) diff --git a/.github/workflows/freeze-for-pr.yml b/.github/workflows/freeze-for-pr.yml index 2dce53029..52918b553 100644 --- a/.github/workflows/freeze-for-pr.yml +++ b/.github/workflows/freeze-for-pr.yml @@ -19,10 +19,10 @@ jobs: with: submodules: "true" - - name: Set up Python 3.9 + - name: Set up Python 3.11 uses: actions/setup-python@0b93645e9fea7318ecaed2b359559ac225c90a2b with: - python-version: "3.9" + python-version: "3.11" - name: install prerequisites run: | diff --git a/.github/workflows/lint.yml b/.github/workflows/lint.yml index 34fe091f6..47494672b 100644 --- a/.github/workflows/lint.yml +++ b/.github/workflows/lint.yml @@ -24,10 +24,10 @@ jobs: with: submodules: "true" - - name: Set up Python 3.9 + - name: Set up Python 3.11 uses: actions/setup-python@0b93645e9fea7318ecaed2b359559ac225c90a2b with: - python-version: "3.9" + python-version: "3.11" - name: install prerequisites run: | diff --git a/.github/workflows/pr-docs.yml b/.github/workflows/pr-docs.yml index 3f6ae03f6..7d9863e22 100644 --- a/.github/workflows/pr-docs.yml +++ b/.github/workflows/pr-docs.yml @@ -28,11 +28,11 @@ jobs: repository: ${{ github.event.pull_request.head.repo.full_name }} submodules: "true" - - name: Set up Python 3.9 + - name: Set up Python 3.11 if: github.event.action != 'closed' uses: actions/setup-python@0b93645e9fea7318ecaed2b359559ac225c90a2b with: - python-version: "3.9" + python-version: "3.11" - name: install prerequisites if: github.event.action != 'closed' diff --git a/.github/workflows/publish.yml b/.github/workflows/publish.yml index 8209aefe6..0be025cd5 100644 --- a/.github/workflows/publish.yml +++ b/.github/workflows/publish.yml @@ -22,10 +22,10 @@ jobs: with: submodules: "true" - - name: Set up Python 3.9 + - name: Set up Python 3.11 uses: actions/setup-python@0b93645e9fea7318ecaed2b359559ac225c90a2b with: - python-version: "3.9" + python-version: "3.11" - name: Build project run: | diff --git a/.github/workflows/py-test.yml b/.github/workflows/py-test.yml index 7dd93a44b..2d3489181 100644 --- a/.github/workflows/py-test.yml +++ b/.github/workflows/py-test.yml @@ -21,7 +21,7 @@ jobs: fail-fast: false matrix: os: [ubuntu-latest, macos-latest, windows-latest] - python-version: ["3.9", "3.10", "3.11", "3.12", "3.13-dev"] + python-version: ["3.11", "3.12", "3.13", "3.14-dev"] runs-on: ${{ matrix.os }} @@ -55,10 +55,10 @@ jobs: with: submodules: "true" - - name: Set up Python 3.9 + - name: Set up Python 3.11 uses: actions/setup-python@0b93645e9fea7318ecaed2b359559ac225c90a2b with: - python-version: "3.9" + python-version: "3.11" - name: install prerequisites run: | diff --git a/.github/workflows/reformat.yml b/.github/workflows/reformat.yml index 5c0660b4c..6095e9ae0 100644 --- a/.github/workflows/reformat.yml +++ b/.github/workflows/reformat.yml @@ -18,10 +18,10 @@ jobs: with: submodules: "true" - - name: Set up Python 3.9 + - name: Set up Python 3.11 uses: actions/setup-python@0b93645e9fea7318ecaed2b359559ac225c90a2b with: - python-version: "3.9" + python-version: "3.11" - name: install prerequisites run: | diff --git a/.github/workflows/release-docs.yml b/.github/workflows/release-docs.yml index 13ed2355d..e482cd0a1 100644 --- a/.github/workflows/release-docs.yml +++ b/.github/workflows/release-docs.yml @@ -13,10 +13,10 @@ jobs: with: submodules: "true" - - name: Set up Python 3.9 + - name: Set up Python 3.11 uses: actions/setup-python@0b93645e9fea7318ecaed2b359559ac225c90a2b with: - python-version: "3.9" + python-version: "3.11" - name: Install prerequisites run: | diff --git a/.github/workflows/type-check.yml b/.github/workflows/type-check.yml index 937e4e273..b39ecbdad 100644 --- a/.github/workflows/type-check.yml +++ b/.github/workflows/type-check.yml @@ -24,10 +24,10 @@ jobs: with: submodules: "true" - - name: Set up Python 3.9 + - name: Set up Python 3.11 uses: actions/setup-python@0b93645e9fea7318ecaed2b359559ac225c90a2b with: - python-version: "3.9" + python-version: "3.11" - name: install prerequisites run: | diff --git a/.github/workflows/update-licence.yml b/.github/workflows/update-licence.yml index ef1ead138..da7b7a380 100644 --- a/.github/workflows/update-licence.yml +++ b/.github/workflows/update-licence.yml @@ -14,10 +14,10 @@ jobs: with: submodules: "true" - - name: Set up Python 3.9 + - name: Set up Python 3.11 uses: actions/setup-python@0b93645e9fea7318ecaed2b359559ac225c90a2b with: - python-version: "3.9" + python-version: "3.11" - name: install prerequisites run: | diff --git a/.github/workflows/upgrade-locks.yml b/.github/workflows/upgrade-locks.yml index 1dc018bbb..7197002a4 100644 --- a/.github/workflows/upgrade-locks.yml +++ b/.github/workflows/upgrade-locks.yml @@ -14,10 +14,10 @@ jobs: with: submodules: "true" - - name: Set up Python 3.9 + - name: Set up Python 3.11 uses: actions/setup-python@0b93645e9fea7318ecaed2b359559ac225c90a2b with: - python-version: "3.9" + python-version: "3.11" - name: install prerequisites run: | diff --git a/.github/workflows/verify-locks.yml b/.github/workflows/verify-locks.yml index d860d290a..5f3e1d156 100644 --- a/.github/workflows/verify-locks.yml +++ b/.github/workflows/verify-locks.yml @@ -22,10 +22,10 @@ jobs: with: submodules: "true" - - name: Set up Python 3.9 + - name: Set up Python 3.11 uses: actions/setup-python@0b93645e9fea7318ecaed2b359559ac225c90a2b with: - python-version: "3.9" + python-version: "3.11" - name: install prerequisites run: | diff --git a/.github/workflows/verify-types.yml b/.github/workflows/verify-types.yml index 6c0d77343..a9caf5749 100644 --- a/.github/workflows/verify-types.yml +++ b/.github/workflows/verify-types.yml @@ -24,10 +24,10 @@ jobs: with: submodules: "true" - - name: Set up Python 3.9 + - name: Set up Python 3.11 uses: actions/setup-python@0b93645e9fea7318ecaed2b359559ac225c90a2b with: - python-version: "3.9" + python-version: "3.11" - name: install prerequisites run: | From cbf5b42514f83a93eec56a8959e3cd174d6a04fe Mon Sep 17 00:00:00 2001 From: "always-on-duty[bot]" <120557446+always-on-duty[bot]@users.noreply.github.com> Date: Sun, 17 Nov 2024 01:44:11 +0000 Subject: [PATCH 05/14] Freeze PR dependency changes --- dev-requirements/constraints.txt | 33 ++-- dev-requirements/tests.txt | 71 ++++---- dev-requirements/type-checking.txt | 252 +++++------------------------ 3 files changed, 87 insertions(+), 269 deletions(-) diff --git a/dev-requirements/constraints.txt b/dev-requirements/constraints.txt index 6826bbd68..7cb995ba0 100644 --- a/dev-requirements/constraints.txt +++ b/dev-requirements/constraints.txt @@ -2,12 +2,12 @@ # This file is autogenerated by pip-compile-cross-platform # To update, run: # -# pip-compile-cross-platform dev-requirements/constraints.in --output-file dev-requirements/constraints.txt --min-python-version 3.9.0,<3.14 --generate-hashes +# pip-compile-cross-platform dev-requirements/constraints.in --output-file dev-requirements/constraints.txt --min-python-version 3.11.0,<3.14 --generate-hashes # -aiohappyeyeballs==2.4.3 ; python_version >= "3.9" and python_version < "3.14" \ +aiohappyeyeballs==2.4.3 ; python_full_version >= "3.11.0" and python_version < "3.14" \ --hash=sha256:75cf88a15106a5002a8eb1dab212525c00d1f4c0fa96e551c9fbe6f09a621586 \ --hash=sha256:8a7a83727b2756f394ab2895ea0765a0a8c475e3c71e98d43d76f22b4b435572 -aiohttp==3.11.2 ; python_version >= "3.9" and python_version < "3.14" \ +aiohttp==3.11.2 ; python_full_version >= "3.11.0" and python_version < "3.14" \ --hash=sha256:08ebe7a1d6c1e5ca766d68407280d69658f5f98821c2ba6c41c63cabfed159af \ --hash=sha256:0a90a0dc4b054b5af299a900bf950fe8f9e3e54322bc405005f30aa5cacc5c98 \ --hash=sha256:0cba0b8d25aa2d450762f3dd6df85498f5e7c3ad0ddeb516ef2b03510f0eea32 \ @@ -84,25 +84,22 @@ aiohttp==3.11.2 ; python_version >= "3.9" and python_version < "3.14" \ --hash=sha256:f833a80d9de9307d736b6af58c235b17ef7f90ebea7b9c49cd274dec7a66a2f1 \ --hash=sha256:fb0544a0e8294a5a5e20d3cacdaaa9a911d7c0a9150f5264aef36e7d8fdfa07e \ --hash=sha256:ff5d22eece44528023254b595c670dfcf9733ac6af74c4b6cb4f6a784dc3870c -aiosignal==1.3.1 ; python_version >= "3.9" and python_version < "3.14" \ +aiosignal==1.3.1 ; python_full_version >= "3.11.0" and python_version < "3.14" \ --hash=sha256:54cd96e15e1649b75d6c87526a6ff0b6c1b0dd3459f43d9ca11d48c339b68cfc \ --hash=sha256:f8376fb07dd1e86a584e4fcdec80b36b7f81aac666ebc724e2c090300dd83b17 -alluka==0.3.3 ; python_full_version >= "3.9.0" and python_version < "3.14" \ +alluka==0.3.3 ; python_full_version >= "3.11.0" and python_version < "3.14" \ --hash=sha256:4d686949e1c28a23831584aec1ea7151c2e2234bb6369115e7c421a2af6cce7d \ --hash=sha256:92d254d7ab073275ce385bb1a2c4bec1c4eb26bbfd2aae7b57e5f8554cb4a037 -async-timeout==5.0.1 ; python_version >= "3.9" and python_version < "3.11" \ - --hash=sha256:39e3809566ff85354557ec2398b55e096c8364bacac9405a7a1fa429e77fe76c \ - --hash=sha256:d9321a7a3d5a6a5e187e824d2fa0793ce379a202935782d555d6e9d2735677d3 -attrs==24.2.0 ; python_version >= "3.9" and python_version < "3.14" \ +attrs==24.2.0 ; python_full_version >= "3.11.0" and python_version < "3.14" \ --hash=sha256:5cfb1b9148b5b086569baec03f20d7b6bf3bcacc9a42bebf87ffaaca362f6346 \ --hash=sha256:81921eb96de3191c8258c199618104dd27ac608d9366f5e35d011eae1867ede2 -colorama==0.4.6 ; python_full_version >= "3.9.0" and python_version < "3.14" and sys_platform == "win32" \ +colorama==0.4.6 ; python_full_version >= "3.11.0" and python_version < "3.14" and sys_platform == "win32" \ --hash=sha256:08695f5cb7ed6e0531a20572697297273c47b8cae5a63ffc6d6ed5c201be6e44 \ --hash=sha256:4f1d9991f5acc0ca119f9d443620b77f9d6b33703e51011c16baf57afb285fc6 -colorlog==6.9.0 ; python_full_version >= "3.9.0" and python_version < "3.14" \ +colorlog==6.9.0 ; python_full_version >= "3.11.0" and python_version < "3.14" \ --hash=sha256:5906e71acd67cb07a71e779c47c4bcb45fb8c2993eebe9e5adcd6a6f1b283eff \ --hash=sha256:bfba54a1b93b94f54e1f4fe48395725a3d92fd2a4af702f6bd70946bdc0c6ac2 -frozenlist==1.5.0 ; python_version >= "3.9" and python_version < "3.14" \ +frozenlist==1.5.0 ; python_full_version >= "3.11.0" and python_version < "3.14" \ --hash=sha256:000a77d6034fbad9b6bb880f7ec073027908f1b40254b5d6f26210d2dab1240e \ --hash=sha256:03d33c2ddbc1816237a67f66336616416e2bbb6beb306e5f890f2eb22b959cdf \ --hash=sha256:04a5c6babd5e8fb7d3c871dc8b321166b80e41b637c31a995ed844a6139942b6 \ @@ -195,13 +192,13 @@ frozenlist==1.5.0 ; python_version >= "3.9" and python_version < "3.14" \ --hash=sha256:f5f9da7f5dbc00a604fe74aa02ae7c98bcede8a3b8b9666f9f86fc13993bc71a \ --hash=sha256:fd74520371c3c4175142d02a976aee0b4cb4a7cc912a60586ffd8d5929979b30 \ --hash=sha256:feeb64bc9bcc6b45c6311c9e9b99406660a9c05ca8a5b30d14a78555088b0b3a -hikari==2.1.0 ; python_full_version >= "3.9.0" and python_version < "3.14" \ +hikari==2.1.0 ; python_full_version >= "3.11.0" and python_version < "3.14" \ --hash=sha256:36d2629f5f1df39d3edc7bb8f64996e82f6926f297e18ababcf753120f7f404b \ --hash=sha256:498bc39d2777eb5ceeec63e3b08362dda39d966a0f2197867f94e8293bb4a277 -idna==3.10 ; python_version >= "3.9" and python_version < "3.14" \ +idna==3.10 ; python_full_version >= "3.11.0" and python_version < "3.14" \ --hash=sha256:12f65c9b470abda6dc35cf8e63cc574b1c52b11df2c86030af0ac09b01b13ea9 \ --hash=sha256:946d195a0d259cbba61165e88e65941f16e9b36ea6ddb97f00452bae8b1287d3 -multidict==6.1.0 ; python_version >= "3.9" and python_version < "3.14" \ +multidict==6.1.0 ; python_full_version >= "3.11.0" and python_version < "3.14" \ --hash=sha256:052e10d2d37810b99cc170b785945421141bf7bb7d2f8799d431e7db229c385f \ --hash=sha256:06809f4f0f7ab7ea2cabf9caca7d79c22c0758b58a71f9d32943ae13c7ace056 \ --hash=sha256:071120490b47aa997cca00666923a83f02c7fbb44f71cf7f136df753f7fa8761 \ @@ -294,7 +291,7 @@ multidict==6.1.0 ; python_version >= "3.9" and python_version < "3.14" \ --hash=sha256:f67f217af4b1ff66c68a87318012de788dd95fcfeb24cc889011f4e1c7454dfd \ --hash=sha256:f90c822a402cb865e396a504f9fc8173ef34212a342d92e362ca498cad308e28 \ --hash=sha256:ff3827aef427c89a25cc96ded1759271a93603aba9fb977a6d264648ebf989db -propcache==0.2.0 ; python_version >= "3.9" and python_version < "3.14" \ +propcache==0.2.0 ; python_full_version >= "3.11.0" and python_version < "3.14" \ --hash=sha256:00181262b17e517df2cd85656fcd6b4e70946fe62cd625b9d74ac9977b64d8d9 \ --hash=sha256:0e53cb83fdd61cbd67202735e6a6687a7b491c8742dfc39c9e01e80354956763 \ --hash=sha256:1235c01ddaa80da8235741e80815ce381c5267f96cc49b1477fdcf8c047ef325 \ @@ -393,10 +390,10 @@ propcache==0.2.0 ; python_version >= "3.9" and python_version < "3.14" \ --hash=sha256:fa1076244f54bb76e65e22cb6910365779d5c3d71d1f18b275f1dfc7b0d71b4d \ --hash=sha256:fc2db02409338bf36590aa985a461b2c96fce91f8e7e0f14c50c5fcc4f229016 \ --hash=sha256:ffcad6c564fe6b9b8916c1aefbb37a362deebf9394bd2974e9d84232e3e08504 -typing-extensions==4.12.2 ; python_version >= "3.9" and python_version < "3.14" \ +typing-extensions==4.12.2 ; python_full_version >= "3.11.0" and python_version < "3.14" \ --hash=sha256:04e5ca0351e0f3f85c6853954072df659d0d13fac324d0072316b67d7794700d \ --hash=sha256:1a7ead55c7e559dd4dee8856e3a88b41225abfe1ce8df57b7c13915fe121ffb8 -yarl==1.17.1 ; python_version >= "3.9" and python_version < "3.14" \ +yarl==1.17.1 ; python_full_version >= "3.11.0" and python_version < "3.14" \ --hash=sha256:06157fb3c58f2736a5e47c8fcbe1afc8b5de6fb28b14d25574af9e62150fcaac \ --hash=sha256:067a63fcfda82da6b198fa73079b1ca40b7c9b7994995b6ee38acda728b64d47 \ --hash=sha256:0b1794853124e2f663f0ea54efb0340b457f08d40a1cef78edfa086576179c91 \ diff --git a/dev-requirements/tests.txt b/dev-requirements/tests.txt index b3add1991..193211970 100644 --- a/dev-requirements/tests.txt +++ b/dev-requirements/tests.txt @@ -2,12 +2,12 @@ # This file is autogenerated by pip-compile-cross-platform # To update, run: # -# pip-compile-cross-platform dev-requirements/tests.in --output-file dev-requirements/tests.txt --min-python-version 3.9.0,<3.14 --generate-hashes +# pip-compile-cross-platform dev-requirements/tests.in --output-file dev-requirements/tests.txt --min-python-version 3.11.0,<3.14 --generate-hashes # -aiohappyeyeballs==2.4.3 ; python_version >= "3.9" and python_version < "3.14" \ +aiohappyeyeballs==2.4.3 ; python_full_version >= "3.11.0" and python_version < "3.14" \ --hash=sha256:75cf88a15106a5002a8eb1dab212525c00d1f4c0fa96e551c9fbe6f09a621586 \ --hash=sha256:8a7a83727b2756f394ab2895ea0765a0a8c475e3c71e98d43d76f22b4b435572 -aiohttp==3.11.2 ; python_version >= "3.9" and python_version < "3.14" \ +aiohttp==3.11.2 ; python_full_version >= "3.11.0" and python_version < "3.14" \ --hash=sha256:08ebe7a1d6c1e5ca766d68407280d69658f5f98821c2ba6c41c63cabfed159af \ --hash=sha256:0a90a0dc4b054b5af299a900bf950fe8f9e3e54322bc405005f30aa5cacc5c98 \ --hash=sha256:0cba0b8d25aa2d450762f3dd6df85498f5e7c3ad0ddeb516ef2b03510f0eea32 \ @@ -84,25 +84,22 @@ aiohttp==3.11.2 ; python_version >= "3.9" and python_version < "3.14" \ --hash=sha256:f833a80d9de9307d736b6af58c235b17ef7f90ebea7b9c49cd274dec7a66a2f1 \ --hash=sha256:fb0544a0e8294a5a5e20d3cacdaaa9a911d7c0a9150f5264aef36e7d8fdfa07e \ --hash=sha256:ff5d22eece44528023254b595c670dfcf9733ac6af74c4b6cb4f6a784dc3870c -aiosignal==1.3.1 ; python_version >= "3.9" and python_version < "3.14" \ +aiosignal==1.3.1 ; python_full_version >= "3.11.0" and python_version < "3.14" \ --hash=sha256:54cd96e15e1649b75d6c87526a6ff0b6c1b0dd3459f43d9ca11d48c339b68cfc \ --hash=sha256:f8376fb07dd1e86a584e4fcdec80b36b7f81aac666ebc724e2c090300dd83b17 -alluka==0.3.3 ; python_full_version >= "3.9.0" and python_version < "3.14" \ +alluka==0.3.3 ; python_full_version >= "3.11.0" and python_version < "3.14" \ --hash=sha256:4d686949e1c28a23831584aec1ea7151c2e2234bb6369115e7c421a2af6cce7d \ --hash=sha256:92d254d7ab073275ce385bb1a2c4bec1c4eb26bbfd2aae7b57e5f8554cb4a037 -async-timeout==5.0.1 ; python_version >= "3.9" and python_version < "3.11" \ - --hash=sha256:39e3809566ff85354557ec2398b55e096c8364bacac9405a7a1fa429e77fe76c \ - --hash=sha256:d9321a7a3d5a6a5e187e824d2fa0793ce379a202935782d555d6e9d2735677d3 -attrs==24.2.0 ; python_version >= "3.9" and python_version < "3.14" \ +attrs==24.2.0 ; python_full_version >= "3.11.0" and python_version < "3.14" \ --hash=sha256:5cfb1b9148b5b086569baec03f20d7b6bf3bcacc9a42bebf87ffaaca362f6346 \ --hash=sha256:81921eb96de3191c8258c199618104dd27ac608d9366f5e35d011eae1867ede2 -colorama==0.4.6 ; python_version >= "3.9" and python_version < "3.14" and sys_platform == "win32" \ +colorama==0.4.6 ; python_full_version >= "3.11.0" and python_version < "3.14" and sys_platform == "win32" \ --hash=sha256:08695f5cb7ed6e0531a20572697297273c47b8cae5a63ffc6d6ed5c201be6e44 \ --hash=sha256:4f1d9991f5acc0ca119f9d443620b77f9d6b33703e51011c16baf57afb285fc6 -colorlog==6.9.0 ; python_full_version >= "3.9.0" and python_version < "3.14" \ +colorlog==6.9.0 ; python_full_version >= "3.11.0" and python_version < "3.14" \ --hash=sha256:5906e71acd67cb07a71e779c47c4bcb45fb8c2993eebe9e5adcd6a6f1b283eff \ --hash=sha256:bfba54a1b93b94f54e1f4fe48395725a3d92fd2a4af702f6bd70946bdc0c6ac2 -coverage[toml]==7.6.7 ; python_version >= "3.9" and python_version < "3.14" \ +coverage[toml]==7.6.7 ; python_full_version >= "3.11.0" and python_version < "3.14" \ --hash=sha256:0266b62cbea568bd5e93a4da364d05de422110cbed5056d69339bd5af5685433 \ --hash=sha256:0573f5cbf39114270842d01872952d301027d2d6e2d84013f30966313cadb529 \ --hash=sha256:0ddcb70b3a3a57581b450571b31cb774f23eb9519c2aaa6176d3a84c9fc57671 \ @@ -165,16 +162,13 @@ coverage[toml]==7.6.7 ; python_version >= "3.9" and python_version < "3.14" \ --hash=sha256:f3e8796434a8106b3ac025fd15417315d7a58ee3e600ad4dbcfddc3f4b14342c \ --hash=sha256:f63e21ed474edd23f7501f89b53280014436e383a14b9bd77a648366c81dce7b \ --hash=sha256:fd49c01e5057a451c30c9b892948976f5d38f2cbd04dc556a82743ba8e27ed8c -exceptiongroup==1.2.2 ; python_version >= "3.9" and python_version < "3.11" \ - --hash=sha256:3111b9d131c238bec2f8f516e123e14ba243563fb135d3fe885990585aa7795b \ - --hash=sha256:47c2edf7c6738fafb49fd34290706d1a1a2f4d1c6df275526b62cbb4aa5393cc -execnet==2.1.1 ; python_full_version >= "3.9.0" and python_version < "3.14" \ +execnet==2.1.1 ; python_full_version >= "3.11.0" and python_version < "3.14" \ --hash=sha256:26dee51f1b80cebd6d0ca8e74dd8745419761d3bef34163928cbebbdc4749fdc \ --hash=sha256:5189b52c6121c24feae288166ab41b32549c7e2348652736540b9e6e7d4e72e3 -freezegun==1.5.1 ; python_full_version >= "3.9.0" and python_version < "3.14" \ +freezegun==1.5.1 ; python_full_version >= "3.11.0" and python_version < "3.14" \ --hash=sha256:b29dedfcda6d5e8e083ce71b2b542753ad48cfec44037b3fc79702e2980a89e9 \ --hash=sha256:bf111d7138a8abe55ab48a71755673dbaa4ab87f4cff5634a4442dfec34c15f1 -frozenlist==1.5.0 ; python_version >= "3.9" and python_version < "3.14" \ +frozenlist==1.5.0 ; python_full_version >= "3.11.0" and python_version < "3.14" \ --hash=sha256:000a77d6034fbad9b6bb880f7ec073027908f1b40254b5d6f26210d2dab1240e \ --hash=sha256:03d33c2ddbc1816237a67f66336616416e2bbb6beb306e5f890f2eb22b959cdf \ --hash=sha256:04a5c6babd5e8fb7d3c871dc8b321166b80e41b637c31a995ed844a6139942b6 \ @@ -267,19 +261,19 @@ frozenlist==1.5.0 ; python_version >= "3.9" and python_version < "3.14" \ --hash=sha256:f5f9da7f5dbc00a604fe74aa02ae7c98bcede8a3b8b9666f9f86fc13993bc71a \ --hash=sha256:fd74520371c3c4175142d02a976aee0b4cb4a7cc912a60586ffd8d5929979b30 \ --hash=sha256:feeb64bc9bcc6b45c6311c9e9b99406660a9c05ca8a5b30d14a78555088b0b3a -hikari==2.1.0 ; python_full_version >= "3.9.0" and python_version < "3.14" \ +hikari==2.1.0 ; python_full_version >= "3.11.0" and python_version < "3.14" \ --hash=sha256:36d2629f5f1df39d3edc7bb8f64996e82f6926f297e18ababcf753120f7f404b \ --hash=sha256:498bc39d2777eb5ceeec63e3b08362dda39d966a0f2197867f94e8293bb4a277 -idna==3.10 ; python_version >= "3.9" and python_version < "3.14" \ +idna==3.10 ; python_full_version >= "3.11.0" and python_version < "3.14" \ --hash=sha256:12f65c9b470abda6dc35cf8e63cc574b1c52b11df2c86030af0ac09b01b13ea9 \ --hash=sha256:946d195a0d259cbba61165e88e65941f16e9b36ea6ddb97f00452bae8b1287d3 -iniconfig==2.0.0 ; python_version >= "3.9" and python_version < "3.14" \ +iniconfig==2.0.0 ; python_full_version >= "3.11.0" and python_version < "3.14" \ --hash=sha256:2d91e135bf72d31a410b17c16da610a82cb55f6b0477d1a902134b24a455b8b3 \ --hash=sha256:b6a85871a79d2e3b22d2d1b94ac2824226a63c6b741c88f7ae975f18b6778374 -mock==5.1.0 ; python_full_version >= "3.9.0" and python_version < "3.14" \ +mock==5.1.0 ; python_full_version >= "3.11.0" and python_version < "3.14" \ --hash=sha256:18c694e5ae8a208cdb3d2c20a993ca1a7b0efa258c247a1e565150f477f83744 \ --hash=sha256:5e96aad5ccda4718e0a229ed94b2024df75cc2d55575ba5762d31f5767b8767d -multidict==6.1.0 ; python_version >= "3.9" and python_version < "3.14" \ +multidict==6.1.0 ; python_full_version >= "3.11.0" and python_version < "3.14" \ --hash=sha256:052e10d2d37810b99cc170b785945421141bf7bb7d2f8799d431e7db229c385f \ --hash=sha256:06809f4f0f7ab7ea2cabf9caca7d79c22c0758b58a71f9d32943ae13c7ace056 \ --hash=sha256:071120490b47aa997cca00666923a83f02c7fbb44f71cf7f136df753f7fa8761 \ @@ -372,13 +366,13 @@ multidict==6.1.0 ; python_version >= "3.9" and python_version < "3.14" \ --hash=sha256:f67f217af4b1ff66c68a87318012de788dd95fcfeb24cc889011f4e1c7454dfd \ --hash=sha256:f90c822a402cb865e396a504f9fc8173ef34212a342d92e362ca498cad308e28 \ --hash=sha256:ff3827aef427c89a25cc96ded1759271a93603aba9fb977a6d264648ebf989db -packaging==24.2 ; python_version >= "3.9" and python_version < "3.14" \ +packaging==24.2 ; python_full_version >= "3.11.0" and python_version < "3.14" \ --hash=sha256:09abb1bccd265c01f4a3aa3f7a7db064b36514d2cba19a2f694fe6150451a759 \ --hash=sha256:c228a6dc5e932d346bc5739379109d49e8853dd8223571c7c5b55260edc0b97f -pluggy==1.5.0 ; python_version >= "3.9" and python_version < "3.14" \ +pluggy==1.5.0 ; python_full_version >= "3.11.0" and python_version < "3.14" \ --hash=sha256:2cffa88e94fdc978c4c574f15f9e59b7f4201d439195c3715ca9e2486f1d0cf1 \ --hash=sha256:44e1ad92c8ca002de6377e165f3e0f1be63266ab4d554740532335b9d75ea669 -propcache==0.2.0 ; python_version >= "3.9" and python_version < "3.14" \ +propcache==0.2.0 ; python_full_version >= "3.11.0" and python_version < "3.14" \ --hash=sha256:00181262b17e517df2cd85656fcd6b4e70946fe62cd625b9d74ac9977b64d8d9 \ --hash=sha256:0e53cb83fdd61cbd67202735e6a6687a7b491c8742dfc39c9e01e80354956763 \ --hash=sha256:1235c01ddaa80da8235741e80815ce381c5267f96cc49b1477fdcf8c047ef325 \ @@ -477,40 +471,37 @@ propcache==0.2.0 ; python_version >= "3.9" and python_version < "3.14" \ --hash=sha256:fa1076244f54bb76e65e22cb6910365779d5c3d71d1f18b275f1dfc7b0d71b4d \ --hash=sha256:fc2db02409338bf36590aa985a461b2c96fce91f8e7e0f14c50c5fcc4f229016 \ --hash=sha256:ffcad6c564fe6b9b8916c1aefbb37a362deebf9394bd2974e9d84232e3e08504 -pytest-asyncio==0.23.8 ; python_full_version >= "3.9.0" and python_version < "3.14" \ +pytest-asyncio==0.23.8 ; python_full_version >= "3.11.0" and python_version < "3.14" \ --hash=sha256:50265d892689a5faefb84df80819d1ecef566eb3549cf915dfb33569359d1ce2 \ --hash=sha256:759b10b33a6dc61cce40a8bd5205e302978bbbcc00e279a8b61d9a6a3c82e4d3 -pytest-cov==6.0.0 ; python_version >= "3.9" and python_version < "3.14" \ +pytest-cov==6.0.0 ; python_full_version >= "3.11.0" and python_version < "3.14" \ --hash=sha256:eee6f1b9e61008bd34975a4d5bab25801eb31898b032dd55addc93e96fcaaa35 \ --hash=sha256:fde0b595ca248bb8e2d76f020b465f3b107c9632e6a1d1705f17834c89dcadc0 -pytest-sugar==1.0.0 ; python_full_version >= "3.9.0" and python_version < "3.14" \ +pytest-sugar==1.0.0 ; python_full_version >= "3.11.0" and python_version < "3.14" \ --hash=sha256:6422e83258f5b0c04ce7c632176c7732cab5fdb909cb39cca5c9139f81276c0a \ --hash=sha256:70ebcd8fc5795dc457ff8b69d266a4e2e8a74ae0c3edc749381c64b5246c8dfd -pytest-timeout==2.3.1 ; python_full_version >= "3.9.0" and python_version < "3.14" \ +pytest-timeout==2.3.1 ; python_full_version >= "3.11.0" and python_version < "3.14" \ --hash=sha256:12397729125c6ecbdaca01035b9e5239d4db97352320af155b3f5de1ba5165d9 \ --hash=sha256:68188cb703edfc6a18fad98dc25a3c61e9f24d644b0b70f33af545219fc7813e -pytest-xdist==3.6.1 ; python_full_version >= "3.9.0" and python_version < "3.14" \ +pytest-xdist==3.6.1 ; python_full_version >= "3.11.0" and python_version < "3.14" \ --hash=sha256:9ed4adfb68a016610848639bb7e02c9352d5d9f03d04809919e2dafc3be4cca7 \ --hash=sha256:ead156a4db231eec769737f57668ef58a2084a34b2e55c4a8fa20d861107300d -pytest==7.4.0 ; python_version >= "3.9" and python_version < "3.14" \ +pytest==7.4.0 ; python_full_version >= "3.11.0" and python_version < "3.14" \ --hash=sha256:78bf16451a2eb8c7a2ea98e32dc119fd2aa758f1d5d66dbf0a59d69a3969df32 \ --hash=sha256:b4bf8c45bd59934ed84001ad51e11b4ee40d40a1229d2c79f9c592b0a3f6bd8a -python-dateutil==2.9.0.post0 ; python_full_version >= "3.9.0" and python_version < "3.14" \ +python-dateutil==2.9.0.post0 ; python_full_version >= "3.11.0" and python_version < "3.14" \ --hash=sha256:37dd54208da7e1cd875388217d5e00ebd4179249f90fb72437e91a35459a0ad3 \ --hash=sha256:a8b2bc7bffae282281c8140a97d3aa9c14da0b136dfe83f850eea9a5f7470427 -six==1.16.0 ; python_full_version >= "3.9.0" and python_version < "3.14" \ +six==1.16.0 ; python_full_version >= "3.11.0" and python_version < "3.14" \ --hash=sha256:1e61c37477a1626458e36f7b1d82aa5c9b094fa4802892072e49de9c60c4c926 \ --hash=sha256:8abb2f1d86890a2dfb989f9a77cfcfd3e47c2a354b01111771326f8aa26e0254 -termcolor==2.5.0 ; python_version >= "3.9" and python_version < "3.14" \ +termcolor==2.5.0 ; python_full_version >= "3.11.0" and python_version < "3.14" \ --hash=sha256:37b17b5fc1e604945c2642c872a3764b5d547a48009871aea3edd3afa180afb8 \ --hash=sha256:998d8d27da6d48442e8e1f016119076b690d962507531df4890fcd2db2ef8a6f -tomli==2.1.0 ; python_version >= "3.9" and python_full_version <= "3.11.0a6" \ - --hash=sha256:3f646cae2aec94e17d04973e4249548320197cfabdf130015d023de4b74d8ab8 \ - --hash=sha256:a5c57c3d1c56f5ccdf89f6523458f60ef716e210fc47c4cfb188c5ba473e0391 -typing-extensions==4.12.2 ; python_version >= "3.9" and python_version < "3.14" \ +typing-extensions==4.12.2 ; python_full_version >= "3.11.0" and python_version < "3.14" \ --hash=sha256:04e5ca0351e0f3f85c6853954072df659d0d13fac324d0072316b67d7794700d \ --hash=sha256:1a7ead55c7e559dd4dee8856e3a88b41225abfe1ce8df57b7c13915fe121ffb8 -yarl==1.17.1 ; python_version >= "3.9" and python_version < "3.14" \ +yarl==1.17.1 ; python_full_version >= "3.11.0" and python_version < "3.14" \ --hash=sha256:06157fb3c58f2736a5e47c8fcbe1afc8b5de6fb28b14d25574af9e62150fcaac \ --hash=sha256:067a63fcfda82da6b198fa73079b1ca40b7c9b7994995b6ee38acda728b64d47 \ --hash=sha256:0b1794853124e2f663f0ea54efb0340b457f08d40a1cef78edfa086576179c91 \ diff --git a/dev-requirements/type-checking.txt b/dev-requirements/type-checking.txt index ad3069a6f..295d35462 100644 --- a/dev-requirements/type-checking.txt +++ b/dev-requirements/type-checking.txt @@ -2,12 +2,12 @@ # This file is autogenerated by pip-compile-cross-platform # To update, run: # -# pip-compile-cross-platform dev-requirements/type-checking.in --output-file dev-requirements/type-checking.txt --min-python-version 3.9.0,<3.14 --generate-hashes +# pip-compile-cross-platform dev-requirements/type-checking.in --output-file dev-requirements/type-checking.txt --min-python-version 3.11.0,<3.14 --generate-hashes # -aiohappyeyeballs==2.4.3 ; python_version >= "3.9" and python_version < "3.14" \ +aiohappyeyeballs==2.4.3 ; python_full_version >= "3.11.0" and python_version < "3.14" \ --hash=sha256:75cf88a15106a5002a8eb1dab212525c00d1f4c0fa96e551c9fbe6f09a621586 \ --hash=sha256:8a7a83727b2756f394ab2895ea0765a0a8c475e3c71e98d43d76f22b4b435572 -aiohttp==3.11.2 ; python_version >= "3.9" and python_version < "3.14" \ +aiohttp==3.11.2 ; python_full_version >= "3.11.0" and python_version < "3.14" \ --hash=sha256:08ebe7a1d6c1e5ca766d68407280d69658f5f98821c2ba6c41c63cabfed159af \ --hash=sha256:0a90a0dc4b054b5af299a900bf950fe8f9e3e54322bc405005f30aa5cacc5c98 \ --hash=sha256:0cba0b8d25aa2d450762f3dd6df85498f5e7c3ad0ddeb516ef2b03510f0eea32 \ @@ -84,31 +84,25 @@ aiohttp==3.11.2 ; python_version >= "3.9" and python_version < "3.14" \ --hash=sha256:f833a80d9de9307d736b6af58c235b17ef7f90ebea7b9c49cd274dec7a66a2f1 \ --hash=sha256:fb0544a0e8294a5a5e20d3cacdaaa9a911d7c0a9150f5264aef36e7d8fdfa07e \ --hash=sha256:ff5d22eece44528023254b595c670dfcf9733ac6af74c4b6cb4f6a784dc3870c -aiosignal==1.3.1 ; python_version >= "3.9" and python_version < "3.14" \ +aiosignal==1.3.1 ; python_full_version >= "3.11.0" and python_version < "3.14" \ --hash=sha256:54cd96e15e1649b75d6c87526a6ff0b6c1b0dd3459f43d9ca11d48c339b68cfc \ --hash=sha256:f8376fb07dd1e86a584e4fcdec80b36b7f81aac666ebc724e2c090300dd83b17 -alluka==0.3.3 ; python_full_version >= "3.9.0" and python_version < "3.14" \ +alluka==0.3.3 ; python_full_version >= "3.11.0" and python_version < "3.14" \ --hash=sha256:4d686949e1c28a23831584aec1ea7151c2e2234bb6369115e7c421a2af6cce7d \ --hash=sha256:92d254d7ab073275ce385bb1a2c4bec1c4eb26bbfd2aae7b57e5f8554cb4a037 -annotated-types==0.7.0 ; python_full_version >= "3.9.0" and python_version < "3.14" \ - --hash=sha256:1f02e8b43a8fbbc3f3e0d4f0f4bfc8131bcb4eebe8849b8e5c773f3a1c582a53 \ - --hash=sha256:aff07c09a53a08bc8cfccb9c85b05f1aa9a2a6f23728d790723543408344ce89 -argcomplete==3.5.1 ; python_full_version >= "3.9.0" and python_version < "3.14" \ +argcomplete==3.5.1 ; python_full_version >= "3.11.0" and python_version < "3.14" \ --hash=sha256:1a1d148bdaa3e3b93454900163403df41448a248af01b6e849edc5ac08e6c363 \ --hash=sha256:eb1ee355aa2557bd3d0145de7b06b2a45b0ce461e1e7813f5d066039ab4177b4 -async-timeout==5.0.1 ; python_version >= "3.9" and python_version < "3.11" \ - --hash=sha256:39e3809566ff85354557ec2398b55e096c8364bacac9405a7a1fa429e77fe76c \ - --hash=sha256:d9321a7a3d5a6a5e187e824d2fa0793ce379a202935782d555d6e9d2735677d3 -attrs==24.2.0 ; python_version >= "3.9" and python_version < "3.14" \ +attrs==24.2.0 ; python_full_version >= "3.11.0" and python_version < "3.14" \ --hash=sha256:5cfb1b9148b5b086569baec03f20d7b6bf3bcacc9a42bebf87ffaaca362f6346 \ --hash=sha256:81921eb96de3191c8258c199618104dd27ac608d9366f5e35d011eae1867ede2 -colorama==0.4.6 ; python_version >= "3.9" and python_version < "3.14" and sys_platform == "win32" \ +colorama==0.4.6 ; python_full_version >= "3.11.0" and python_version < "3.14" and sys_platform == "win32" \ --hash=sha256:08695f5cb7ed6e0531a20572697297273c47b8cae5a63ffc6d6ed5c201be6e44 \ --hash=sha256:4f1d9991f5acc0ca119f9d443620b77f9d6b33703e51011c16baf57afb285fc6 -colorlog==6.9.0 ; python_full_version >= "3.9.0" and python_version < "3.14" \ +colorlog==6.9.0 ; python_full_version >= "3.11.0" and python_version < "3.14" \ --hash=sha256:5906e71acd67cb07a71e779c47c4bcb45fb8c2993eebe9e5adcd6a6f1b283eff \ --hash=sha256:bfba54a1b93b94f54e1f4fe48395725a3d92fd2a4af702f6bd70946bdc0c6ac2 -coverage[toml]==7.6.7 ; python_version >= "3.9" and python_version < "3.14" \ +coverage[toml]==7.6.7 ; python_full_version >= "3.11.0" and python_version < "3.14" \ --hash=sha256:0266b62cbea568bd5e93a4da364d05de422110cbed5056d69339bd5af5685433 \ --hash=sha256:0573f5cbf39114270842d01872952d301027d2d6e2d84013f30966313cadb529 \ --hash=sha256:0ddcb70b3a3a57581b450571b31cb774f23eb9519c2aaa6176d3a84c9fc57671 \ @@ -171,22 +165,19 @@ coverage[toml]==7.6.7 ; python_version >= "3.9" and python_version < "3.14" \ --hash=sha256:f3e8796434a8106b3ac025fd15417315d7a58ee3e600ad4dbcfddc3f4b14342c \ --hash=sha256:f63e21ed474edd23f7501f89b53280014436e383a14b9bd77a648366c81dce7b \ --hash=sha256:fd49c01e5057a451c30c9b892948976f5d38f2cbd04dc556a82743ba8e27ed8c -distlib==0.3.9 ; python_full_version >= "3.9.0" and python_version < "3.14" \ +distlib==0.3.9 ; python_full_version >= "3.11.0" and python_version < "3.14" \ --hash=sha256:47f8c22fd27c27e25a65601af709b38e4f0a45ea4fc2e710f65755fa8caaaf87 \ --hash=sha256:a60f20dea646b8a33f3e7772f74dc0b2d0772d2837ee1342a00645c81edf9403 -exceptiongroup==1.2.2 ; python_version >= "3.9" and python_version < "3.11" \ - --hash=sha256:3111b9d131c238bec2f8f516e123e14ba243563fb135d3fe885990585aa7795b \ - --hash=sha256:47c2edf7c6738fafb49fd34290706d1a1a2f4d1c6df275526b62cbb4aa5393cc -execnet==2.1.1 ; python_full_version >= "3.9.0" and python_version < "3.14" \ +execnet==2.1.1 ; python_full_version >= "3.11.0" and python_version < "3.14" \ --hash=sha256:26dee51f1b80cebd6d0ca8e74dd8745419761d3bef34163928cbebbdc4749fdc \ --hash=sha256:5189b52c6121c24feae288166ab41b32549c7e2348652736540b9e6e7d4e72e3 -filelock==3.16.1 ; python_full_version >= "3.9.0" and python_version < "3.14" \ +filelock==3.16.1 ; python_full_version >= "3.11.0" and python_version < "3.14" \ --hash=sha256:2082e5703d51fbf98ea75855d9d5527e33d8ff23099bec374a134febee6946b0 \ --hash=sha256:c249fbfcd5db47e5e2d6d62198e565475ee65e4831e2561c8e313fa7eb961435 -freezegun==1.5.1 ; python_full_version >= "3.9.0" and python_version < "3.14" \ +freezegun==1.5.1 ; python_full_version >= "3.11.0" and python_version < "3.14" \ --hash=sha256:b29dedfcda6d5e8e083ce71b2b542753ad48cfec44037b3fc79702e2980a89e9 \ --hash=sha256:bf111d7138a8abe55ab48a71755673dbaa4ab87f4cff5634a4442dfec34c15f1 -frozenlist==1.5.0 ; python_version >= "3.9" and python_version < "3.14" \ +frozenlist==1.5.0 ; python_full_version >= "3.11.0" and python_version < "3.14" \ --hash=sha256:000a77d6034fbad9b6bb880f7ec073027908f1b40254b5d6f26210d2dab1240e \ --hash=sha256:03d33c2ddbc1816237a67f66336616416e2bbb6beb306e5f890f2eb22b959cdf \ --hash=sha256:04a5c6babd5e8fb7d3c871dc8b321166b80e41b637c31a995ed844a6139942b6 \ @@ -279,84 +270,19 @@ frozenlist==1.5.0 ; python_version >= "3.9" and python_version < "3.14" \ --hash=sha256:f5f9da7f5dbc00a604fe74aa02ae7c98bcede8a3b8b9666f9f86fc13993bc71a \ --hash=sha256:fd74520371c3c4175142d02a976aee0b4cb4a7cc912a60586ffd8d5929979b30 \ --hash=sha256:feeb64bc9bcc6b45c6311c9e9b99406660a9c05ca8a5b30d14a78555088b0b3a -hikari==2.1.0 ; python_full_version >= "3.9.0" and python_version < "3.14" \ +hikari==2.1.0 ; python_full_version >= "3.11.0" and python_version < "3.14" \ --hash=sha256:36d2629f5f1df39d3edc7bb8f64996e82f6926f297e18ababcf753120f7f404b \ --hash=sha256:498bc39d2777eb5ceeec63e3b08362dda39d966a0f2197867f94e8293bb4a277 -idna==3.10 ; python_version >= "3.9" and python_version < "3.14" \ +idna==3.10 ; python_full_version >= "3.11.0" and python_version < "3.14" \ --hash=sha256:12f65c9b470abda6dc35cf8e63cc574b1c52b11df2c86030af0ac09b01b13ea9 \ --hash=sha256:946d195a0d259cbba61165e88e65941f16e9b36ea6ddb97f00452bae8b1287d3 -iniconfig==2.0.0 ; python_version >= "3.9" and python_version < "3.14" \ +iniconfig==2.0.0 ; python_full_version >= "3.11.0" and python_version < "3.14" \ --hash=sha256:2d91e135bf72d31a410b17c16da610a82cb55f6b0477d1a902134b24a455b8b3 \ --hash=sha256:b6a85871a79d2e3b22d2d1b94ac2824226a63c6b741c88f7ae975f18b6778374 -jinja2==3.1.4 ; python_full_version >= "3.9.0" and python_version < "3.14" \ - --hash=sha256:4a3aee7acbbe7303aede8e9648d13b8bf88a429282aa6122a993f0ac800cb369 \ - --hash=sha256:bc5dd2abb727a5319567b7a813e6a2e7318c39f4f487cfe6c89c6f9c7d25197d -markupsafe==3.0.2 ; python_version >= "3.9" and python_version < "3.14" \ - --hash=sha256:0bff5e0ae4ef2e1ae4fdf2dfd5b76c75e5c2fa4132d05fc1b0dabcd20c7e28c4 \ - --hash=sha256:0f4ca02bea9a23221c0182836703cbf8930c5e9454bacce27e767509fa286a30 \ - --hash=sha256:1225beacc926f536dc82e45f8a4d68502949dc67eea90eab715dea3a21c1b5f0 \ - --hash=sha256:131a3c7689c85f5ad20f9f6fb1b866f402c445b220c19fe4308c0b147ccd2ad9 \ - --hash=sha256:15ab75ef81add55874e7ab7055e9c397312385bd9ced94920f2802310c930396 \ - --hash=sha256:1a9d3f5f0901fdec14d8d2f66ef7d035f2157240a433441719ac9a3fba440b13 \ - --hash=sha256:1c99d261bd2d5f6b59325c92c73df481e05e57f19837bdca8413b9eac4bd8028 \ - --hash=sha256:1e084f686b92e5b83186b07e8a17fc09e38fff551f3602b249881fec658d3eca \ - --hash=sha256:2181e67807fc2fa785d0592dc2d6206c019b9502410671cc905d132a92866557 \ - --hash=sha256:2cb8438c3cbb25e220c2ab33bb226559e7afb3baec11c4f218ffa7308603c832 \ - --hash=sha256:3169b1eefae027567d1ce6ee7cae382c57fe26e82775f460f0b2778beaad66c0 \ - --hash=sha256:3809ede931876f5b2ec92eef964286840ed3540dadf803dd570c3b7e13141a3b \ - --hash=sha256:38a9ef736c01fccdd6600705b09dc574584b89bea478200c5fbf112a6b0d5579 \ - --hash=sha256:3d79d162e7be8f996986c064d1c7c817f6df3a77fe3d6859f6f9e7be4b8c213a \ - --hash=sha256:444dcda765c8a838eaae23112db52f1efaf750daddb2d9ca300bcae1039adc5c \ - --hash=sha256:48032821bbdf20f5799ff537c7ac3d1fba0ba032cfc06194faffa8cda8b560ff \ - --hash=sha256:4aa4e5faecf353ed117801a068ebab7b7e09ffb6e1d5e412dc852e0da018126c \ - --hash=sha256:52305740fe773d09cffb16f8ed0427942901f00adedac82ec8b67752f58a1b22 \ - --hash=sha256:569511d3b58c8791ab4c2e1285575265991e6d8f8700c7be0e88f86cb0672094 \ - --hash=sha256:57cb5a3cf367aeb1d316576250f65edec5bb3be939e9247ae594b4bcbc317dfb \ - --hash=sha256:5b02fb34468b6aaa40dfc198d813a641e3a63b98c2b05a16b9f80b7ec314185e \ - --hash=sha256:6381026f158fdb7c72a168278597a5e3a5222e83ea18f543112b2662a9b699c5 \ - --hash=sha256:6af100e168aa82a50e186c82875a5893c5597a0c1ccdb0d8b40240b1f28b969a \ - --hash=sha256:6c89876f41da747c8d3677a2b540fb32ef5715f97b66eeb0c6b66f5e3ef6f59d \ - --hash=sha256:6e296a513ca3d94054c2c881cc913116e90fd030ad1c656b3869762b754f5f8a \ - --hash=sha256:70a87b411535ccad5ef2f1df5136506a10775d267e197e4cf531ced10537bd6b \ - --hash=sha256:7e94c425039cde14257288fd61dcfb01963e658efbc0ff54f5306b06054700f8 \ - --hash=sha256:846ade7b71e3536c4e56b386c2a47adf5741d2d8b94ec9dc3e92e5e1ee1e2225 \ - --hash=sha256:88416bd1e65dcea10bc7569faacb2c20ce071dd1f87539ca2ab364bf6231393c \ - --hash=sha256:88b49a3b9ff31e19998750c38e030fc7bb937398b1f78cfa599aaef92d693144 \ - --hash=sha256:8c4e8c3ce11e1f92f6536ff07154f9d49677ebaaafc32db9db4620bc11ed480f \ - --hash=sha256:8e06879fc22a25ca47312fbe7c8264eb0b662f6db27cb2d3bbbc74b1df4b9b87 \ - --hash=sha256:9025b4018f3a1314059769c7bf15441064b2207cb3f065e6ea1e7359cb46db9d \ - --hash=sha256:93335ca3812df2f366e80509ae119189886b0f3c2b81325d39efdb84a1e2ae93 \ - --hash=sha256:9778bd8ab0a994ebf6f84c2b949e65736d5575320a17ae8984a77fab08db94cf \ - --hash=sha256:9e2d922824181480953426608b81967de705c3cef4d1af983af849d7bd619158 \ - --hash=sha256:a123e330ef0853c6e822384873bef7507557d8e4a082961e1defa947aa59ba84 \ - --hash=sha256:a904af0a6162c73e3edcb969eeeb53a63ceeb5d8cf642fade7d39e7963a22ddb \ - --hash=sha256:ad10d3ded218f1039f11a75f8091880239651b52e9bb592ca27de44eed242a48 \ - --hash=sha256:b424c77b206d63d500bcb69fa55ed8d0e6a3774056bdc4839fc9298a7edca171 \ - --hash=sha256:b5a6b3ada725cea8a5e634536b1b01c30bcdcd7f9c6fff4151548d5bf6b3a36c \ - --hash=sha256:ba8062ed2cf21c07a9e295d5b8a2a5ce678b913b45fdf68c32d95d6c1291e0b6 \ - --hash=sha256:ba9527cdd4c926ed0760bc301f6728ef34d841f405abf9d4f959c478421e4efd \ - --hash=sha256:bbcb445fa71794da8f178f0f6d66789a28d7319071af7a496d4d507ed566270d \ - --hash=sha256:bcf3e58998965654fdaff38e58584d8937aa3096ab5354d493c77d1fdd66d7a1 \ - --hash=sha256:c0ef13eaeee5b615fb07c9a7dadb38eac06a0608b41570d8ade51c56539e509d \ - --hash=sha256:cabc348d87e913db6ab4aa100f01b08f481097838bdddf7c7a84b7575b7309ca \ - --hash=sha256:cdb82a876c47801bb54a690c5ae105a46b392ac6099881cdfb9f6e95e4014c6a \ - --hash=sha256:cfad01eed2c2e0c01fd0ecd2ef42c492f7f93902e39a42fc9ee1692961443a29 \ - --hash=sha256:d16a81a06776313e817c951135cf7340a3e91e8c1ff2fac444cfd75fffa04afe \ - --hash=sha256:d8213e09c917a951de9d09ecee036d5c7d36cb6cb7dbaece4c71a60d79fb9798 \ - --hash=sha256:e07c3764494e3776c602c1e78e298937c3315ccc9043ead7e685b7f2b8d47b3c \ - --hash=sha256:e17c96c14e19278594aa4841ec148115f9c7615a47382ecb6b82bd8fea3ab0c8 \ - --hash=sha256:e444a31f8db13eb18ada366ab3cf45fd4b31e4db1236a4448f68778c1d1a5a2f \ - --hash=sha256:e6a2a455bd412959b57a172ce6328d2dd1f01cb2135efda2e4576e8a23fa3b0f \ - --hash=sha256:eaa0a10b7f72326f1372a713e73c3f739b524b3af41feb43e4921cb529f5929a \ - --hash=sha256:eb7972a85c54febfb25b5c4b4f3af4dcc731994c7da0d8a0b4a6eb0640e1d178 \ - --hash=sha256:ee55d3edf80167e48ea11a923c7386f4669df67d7994554387f84e7d8b0a2bf0 \ - --hash=sha256:f3818cb119498c0678015754eba762e0d61e5b52d34c8b13d770f0719f7b1d79 \ - --hash=sha256:f8b3d067f2e40fe93e1ccdd6b2e1d16c43140e76f02fb1319a05cf2b79d99430 \ - --hash=sha256:fcabf5ff6eea076f859677f5f0b6b5c1a51e70a376b0579e0eadef8db48c6b50 -mock==5.1.0 ; python_full_version >= "3.9.0" and python_version < "3.14" \ +mock==5.1.0 ; python_full_version >= "3.11.0" and python_version < "3.14" \ --hash=sha256:18c694e5ae8a208cdb3d2c20a993ca1a7b0efa258c247a1e565150f477f83744 \ --hash=sha256:5e96aad5ccda4718e0a229ed94b2024df75cc2d55575ba5762d31f5767b8767d -multidict==6.1.0 ; python_version >= "3.9" and python_version < "3.14" \ +multidict==6.1.0 ; python_full_version >= "3.11.0" and python_version < "3.14" \ --hash=sha256:052e10d2d37810b99cc170b785945421141bf7bb7d2f8799d431e7db229c385f \ --hash=sha256:06809f4f0f7ab7ea2cabf9caca7d79c22c0758b58a71f9d32943ae13c7ace056 \ --hash=sha256:071120490b47aa997cca00666923a83f02c7fbb44f71cf7f136df753f7fa8761 \ @@ -449,10 +375,10 @@ multidict==6.1.0 ; python_version >= "3.9" and python_version < "3.14" \ --hash=sha256:f67f217af4b1ff66c68a87318012de788dd95fcfeb24cc889011f4e1c7454dfd \ --hash=sha256:f90c822a402cb865e396a504f9fc8173ef34212a342d92e362ca498cad308e28 \ --hash=sha256:ff3827aef427c89a25cc96ded1759271a93603aba9fb977a6d264648ebf989db -mypy-extensions==1.0.0 ; python_full_version >= "3.9.0" and python_version < "3.14" \ +mypy-extensions==1.0.0 ; python_full_version >= "3.11.0" and python_version < "3.14" \ --hash=sha256:4392f6c0eb8a5668a69e23d168ffa70f0be9ccfd32b5cc2d26a34ae5b844552d \ --hash=sha256:75dbf8955dc00442a438fc4d0666508a9a97b6bd41aa2f0ffe9d2f2725af0782 -mypy==1.13.0 ; python_full_version >= "3.9.0" and python_version < "3.14" \ +mypy==1.13.0 ; python_full_version >= "3.11.0" and python_version < "3.14" \ --hash=sha256:0246bcb1b5de7f08f2826451abd947bf656945209b140d16ed317f65a17dc7dc \ --hash=sha256:0291a61b6fbf3e6673e3405cfcc0e7650bebc7939659fdca2702958038bd835e \ --hash=sha256:0730d1c6a2739d4511dc4253f8274cdd140c55c32dfb0a4cf8b7a43f40abfa6f \ @@ -485,22 +411,22 @@ mypy==1.13.0 ; python_full_version >= "3.9.0" and python_version < "3.14" \ --hash=sha256:bde31fc887c213e223bbfc34328070996061b0833b0a4cfec53745ed61f3519b \ --hash=sha256:c5fc54dbb712ff5e5a0fca797e6e0aa25726c7e72c6a5850cfd2adbc1eb0a372 \ --hash=sha256:de2904956dac40ced10931ac967ae63c5089bd498542194b436eb097a9f77bc8 -nodeenv==1.9.1 ; python_full_version >= "3.9.0" and python_version < "3.14" \ +nodeenv==1.9.1 ; python_full_version >= "3.11.0" and python_version < "3.14" \ --hash=sha256:6ec12890a2dab7946721edbfbcd91f3319c6ccc9aec47be7c7e6b7011ee6645f \ --hash=sha256:ba11c9782d29c27c70ffbdda2d7415098754709be8a7056d79a737cd901155c9 -nox==2024.10.9 ; python_full_version >= "3.9.0" and python_version < "3.14" \ +nox==2024.10.9 ; python_full_version >= "3.11.0" and python_version < "3.14" \ --hash=sha256:1d36f309a0a2a853e9bccb76bbef6bb118ba92fa92674d15604ca99adeb29eab \ --hash=sha256:7aa9dc8d1c27e9f45ab046ffd1c3b2c4f7c91755304769df231308849ebded95 -packaging==24.2 ; python_version >= "3.9" and python_version < "3.14" \ +packaging==24.2 ; python_full_version >= "3.11.0" and python_version < "3.14" \ --hash=sha256:09abb1bccd265c01f4a3aa3f7a7db064b36514d2cba19a2f694fe6150451a759 \ --hash=sha256:c228a6dc5e932d346bc5739379109d49e8853dd8223571c7c5b55260edc0b97f -platformdirs==4.3.6 ; python_full_version >= "3.9.0" and python_version < "3.14" \ +platformdirs==4.3.6 ; python_full_version >= "3.11.0" and python_version < "3.14" \ --hash=sha256:357fb2acbc885b0419afd3ce3ed34564c13c9b95c89360cd9563f73aa5e2b907 \ --hash=sha256:73e575e1408ab8103900836b97580d5307456908a03e92031bab39e4554cc3fb -pluggy==1.5.0 ; python_version >= "3.9" and python_version < "3.14" \ +pluggy==1.5.0 ; python_full_version >= "3.11.0" and python_version < "3.14" \ --hash=sha256:2cffa88e94fdc978c4c574f15f9e59b7f4201d439195c3715ca9e2486f1d0cf1 \ --hash=sha256:44e1ad92c8ca002de6377e165f3e0f1be63266ab4d554740532335b9d75ea669 -propcache==0.2.0 ; python_version >= "3.9" and python_version < "3.14" \ +propcache==0.2.0 ; python_full_version >= "3.11.0" and python_version < "3.14" \ --hash=sha256:00181262b17e517df2cd85656fcd6b4e70946fe62cd625b9d74ac9977b64d8d9 \ --hash=sha256:0e53cb83fdd61cbd67202735e6a6687a7b491c8742dfc39c9e01e80354956763 \ --hash=sha256:1235c01ddaa80da8235741e80815ce381c5267f96cc49b1477fdcf8c047ef325 \ @@ -599,139 +525,43 @@ propcache==0.2.0 ; python_version >= "3.9" and python_version < "3.14" \ --hash=sha256:fa1076244f54bb76e65e22cb6910365779d5c3d71d1f18b275f1dfc7b0d71b4d \ --hash=sha256:fc2db02409338bf36590aa985a461b2c96fce91f8e7e0f14c50c5fcc4f229016 \ --hash=sha256:ffcad6c564fe6b9b8916c1aefbb37a362deebf9394bd2974e9d84232e3e08504 -pydantic-core==2.23.4 ; python_full_version >= "3.9.0" and python_version < "3.14" \ - --hash=sha256:0a7df63886be5e270da67e0966cf4afbae86069501d35c8c1b3b6c168f42cb36 \ - --hash=sha256:0cb3da3fd1b6a5d0279a01877713dbda118a2a4fc6f0d821a57da2e464793f05 \ - --hash=sha256:0dbd8dbed2085ed23b5c04afa29d8fd2771674223135dc9bc937f3c09284d071 \ - --hash=sha256:0dff76e0602ca7d4cdaacc1ac4c005e0ce0dcfe095d5b5259163a80d3a10d327 \ - --hash=sha256:1278e0d324f6908e872730c9102b0112477a7f7cf88b308e4fc36ce1bdb6d58c \ - --hash=sha256:128585782e5bfa515c590ccee4b727fb76925dd04a98864182b22e89a4e6ed36 \ - --hash=sha256:1498bec4c05c9c787bde9125cfdcc63a41004ff167f495063191b863399b1a29 \ - --hash=sha256:19442362866a753485ba5e4be408964644dd6a09123d9416c54cd49171f50744 \ - --hash=sha256:1b84d168f6c48fabd1f2027a3d1bdfe62f92cade1fb273a5d68e621da0e44e6d \ - --hash=sha256:1e90d2e3bd2c3863d48525d297cd143fe541be8bbf6f579504b9712cb6b643ec \ - --hash=sha256:20152074317d9bed6b7a95ade3b7d6054845d70584216160860425f4fbd5ee9e \ - --hash=sha256:216f9b2d7713eb98cb83c80b9c794de1f6b7e3145eef40400c62e86cee5f4e1e \ - --hash=sha256:233710f069d251feb12a56da21e14cca67994eab08362207785cf8c598e74577 \ - --hash=sha256:255a8ef062cbf6674450e668482456abac99a5583bbafb73f9ad469540a3a232 \ - --hash=sha256:2584f7cf844ac4d970fba483a717dbe10c1c1c96a969bf65d61ffe94df1b2863 \ - --hash=sha256:2971bb5ffe72cc0f555c13e19b23c85b654dd2a8f7ab493c262071377bfce9f6 \ - --hash=sha256:29d2c342c4bc01b88402d60189f3df065fb0dda3654744d5a165a5288a657368 \ - --hash=sha256:2e203fdf807ac7e12ab59ca2bfcabb38c7cf0b33c41efeb00f8e5da1d86af480 \ - --hash=sha256:33e3d65a85a2a4a0dc3b092b938a4062b1a05f3a9abde65ea93b233bca0e03f2 \ - --hash=sha256:374a5e5049eda9e0a44c696c7ade3ff355f06b1fe0bb945ea3cac2bc336478a2 \ - --hash=sha256:37b0fe330e4a58d3c58b24d91d1eb102aeec675a3db4c292ec3928ecd892a9a6 \ - --hash=sha256:3d5639516376dce1940ea36edf408c554475369f5da2abd45d44621cb616f769 \ - --hash=sha256:42c6dcb030aefb668a2b7009c85b27f90e51e6a3b4d5c9bc4c57631292015b0d \ - --hash=sha256:4a7cd62e831afe623fbb7aabbb4fe583212115b3ef38a9f6b71869ba644624a2 \ - --hash=sha256:4ba762ed58e8d68657fc1281e9bb72e1c3e79cc5d464be146e260c541ec12d84 \ - --hash=sha256:4fc714bdbfb534f94034efaa6eadd74e5b93c8fa6315565a222f7b6f42ca1166 \ - --hash=sha256:4ffa2ebd4c8530079140dd2d7f794a9d9a73cbb8e9d59ffe24c63436efa8f271 \ - --hash=sha256:5a1504ad17ba4210df3a045132a7baeeba5a200e930f57512ee02909fc5c4cb5 \ - --hash=sha256:5c364564d17da23db1106787675fc7af45f2f7b58b4173bfdd105564e132e6fb \ - --hash=sha256:5e11661ce0fd30a6790e8bcdf263b9ec5988e95e63cf901972107efc49218b13 \ - --hash=sha256:5f54b118ce5de9ac21c363d9b3caa6c800341e8c47a508787e5868c6b79c9323 \ - --hash=sha256:5f5ff8d839f4566a474a969508fe1c5e59c31c80d9e140566f9a37bba7b8d556 \ - --hash=sha256:61817945f2fe7d166e75fbfb28004034b48e44878177fc54d81688e7b85a3665 \ - --hash=sha256:624e278a7d29b6445e4e813af92af37820fafb6dcc55c012c834f9e26f9aaaef \ - --hash=sha256:63e46b3169866bd62849936de036f901a9356e36376079b05efa83caeaa02ceb \ - --hash=sha256:6531b7ca5f951d663c339002e91aaebda765ec7d61b7d1e3991051906ddde119 \ - --hash=sha256:68665f4c17edcceecc112dfed5dbe6f92261fb9d6054b47d01bf6371a6196126 \ - --hash=sha256:696dd8d674d6ce621ab9d45b205df149399e4bb9aa34102c970b721554828510 \ - --hash=sha256:6f783e0ec4803c787bcea93e13e9932edab72068f68ecffdf86a99fd5918878b \ - --hash=sha256:723314c1d51722ab28bfcd5240d858512ffd3116449c557a1336cbe3919beb87 \ - --hash=sha256:74b9127ffea03643e998e0c5ad9bd3811d3dac8c676e47db17b0ee7c3c3bf35f \ - --hash=sha256:7530e201d10d7d14abce4fb54cfe5b94a0aefc87da539d0346a484ead376c3cc \ - --hash=sha256:77733e3892bb0a7fa797826361ce8a9184d25c8dffaec60b7ffe928153680ba8 \ - --hash=sha256:78ddaaa81421a29574a682b3179d4cf9e6d405a09b99d93ddcf7e5239c742e21 \ - --hash=sha256:7c9129eb40958b3d4500fa2467e6a83356b3b61bfff1b414c7361d9220f9ae8f \ - --hash=sha256:7d32706badfe136888bdea71c0def994644e09fff0bfe47441deaed8e96fdbc6 \ - --hash=sha256:81965a16b675b35e1d09dd14df53f190f9129c0202356ed44ab2728b1c905658 \ - --hash=sha256:8394d940e5d400d04cad4f75c0598665cbb81aecefaca82ca85bd28264af7f9b \ - --hash=sha256:86d2f57d3e1379a9525c5ab067b27dbb8a0642fb5d454e17a9ac434f9ce523e3 \ - --hash=sha256:883a91b5dd7d26492ff2f04f40fbb652de40fcc0afe07e8129e8ae779c2110eb \ - --hash=sha256:88ad334a15b32a791ea935af224b9de1bf99bcd62fabf745d5f3442199d86d59 \ - --hash=sha256:9261d3ce84fa1d38ed649c3638feefeae23d32ba9182963e465d58d62203bd24 \ - --hash=sha256:97df63000f4fea395b2824da80e169731088656d1818a11b95f3b173747b6cd9 \ - --hash=sha256:98d134c954828488b153d88ba1f34e14259284f256180ce659e8d83e9c05eaa3 \ - --hash=sha256:996a38a83508c54c78a5f41456b0103c30508fed9abcad0a59b876d7398f25fd \ - --hash=sha256:9a5bce9d23aac8f0cf0836ecfc033896aa8443b501c58d0602dbfd5bd5b37753 \ - --hash=sha256:9a6b5099eeec78827553827f4c6b8615978bb4b6a88e5d9b93eddf8bb6790f55 \ - --hash=sha256:9d18368b137c6295db49ce7218b1a9ba15c5bc254c96d7c9f9e924a9bc7825ad \ - --hash=sha256:a4fa4fc04dff799089689f4fd502ce7d59de529fc2f40a2c8836886c03e0175a \ - --hash=sha256:a5c7ba8ffb6d6f8f2ab08743be203654bb1aaa8c9dcb09f82ddd34eadb695605 \ - --hash=sha256:aea443fffa9fbe3af1a9ba721a87f926fe548d32cab71d188a6ede77d0ff244e \ - --hash=sha256:b10bd51f823d891193d4717448fab065733958bdb6a6b351967bd349d48d5c9b \ - --hash=sha256:ba1a0996f6c2773bd83e63f18914c1de3c9dd26d55f4ac302a7efe93fb8e7433 \ - --hash=sha256:bb2802e667b7051a1bebbfe93684841cc9351004e2badbd6411bf357ab8d5ac8 \ - --hash=sha256:cfdd16ab5e59fc31b5e906d1a3f666571abc367598e3e02c83403acabc092e07 \ - --hash=sha256:d06b0c8da4f16d1d1e352134427cb194a0a6e19ad5db9161bf32b2113409e728 \ - --hash=sha256:d0776dea117cf5272382634bd2a5c1b6eb16767c223c6a5317cd3e2a757c61a0 \ - --hash=sha256:d18ca8148bebe1b0a382a27a8ee60350091a6ddaf475fa05ef50dc35b5df6327 \ - --hash=sha256:d4488a93b071c04dc20f5cecc3631fc78b9789dd72483ba15d423b5b3689b555 \ - --hash=sha256:d5f7a395a8cf1621939692dba2a6b6a830efa6b3cee787d82c7de1ad2930de64 \ - --hash=sha256:d7a80d21d613eec45e3d41eb22f8f94ddc758a6c4720842dc74c0581f54993d6 \ - --hash=sha256:d97683ddee4723ae8c95d1eddac7c192e8c552da0c73a925a89fa8649bf13eea \ - --hash=sha256:dcedcd19a557e182628afa1d553c3895a9f825b936415d0dbd3cd0bbcfd29b4b \ - --hash=sha256:de6d1d1b9e5101508cb37ab0d972357cac5235f5c6533d1071964c47139257df \ - --hash=sha256:df49e7a0861a8c36d089c1ed57d308623d60416dab2647a4a17fe050ba85de0e \ - --hash=sha256:df933278128ea1cd77772673c73954e53a1c95a4fdf41eef97c2b779271bd0bd \ - --hash=sha256:e08277a400de01bc72436a0ccd02bdf596631411f592ad985dcee21445bd0068 \ - --hash=sha256:e38e63e6f3d1cec5a27e0afe90a085af8b6806ee208b33030e65b6516353f1a3 \ - --hash=sha256:e55541f756f9b3ee346b840103f32779c695a19826a4c442b7954550a0972040 \ - --hash=sha256:ec4e55f79b1c4ffb2eecd8a0cfba9955a2588497d96851f4c8f99aa4a1d39b12 \ - --hash=sha256:ed1a53de42fbe34853ba90513cea21673481cd81ed1be739f7f2efb931b24916 \ - --hash=sha256:ed541d70698978a20eb63d8c5d72f2cc6d7079d9d90f6b50bad07826f1320f5f \ - --hash=sha256:f09e2ff1f17c2b51f2bc76d1cc33da96298f0a036a137f5440ab3ec5360b624f \ - --hash=sha256:f220b0eea5965dec25480b6333c788fb72ce5f9129e8759ef876a1d805d00801 \ - --hash=sha256:f3e0da4ebaef65158d4dfd7d3678aad692f7666877df0002b8a522cdf088f231 \ - --hash=sha256:f455ee30a9d61d3e1a15abd5068827773d6e4dc513e795f380cdd59932c782d5 \ - --hash=sha256:f5ef8f42bec47f21d07668a043f077d507e5bf4e668d5c6dfe6aaba89de1a5b8 \ - --hash=sha256:f69a8e0b033b747bb3e36a44e7732f0c99f7edd5cea723d45bc0d6e95377ffee \ - --hash=sha256:ff02b6d461a6de369f07ec15e465a88895f3223eb75073ffea56b84d9331f607 -pydantic==2.9.2 ; python_full_version >= "3.9.0" and python_version < "3.14" \ - --hash=sha256:d155cef71265d1e9807ed1c32b4c8deec042a44a50a4188b25ac67ecd81a9c0f \ - --hash=sha256:f048cec7b26778210e28a0459867920654d48e5e62db0958433636cde4254f12 -pyright==1.1.389 ; python_full_version >= "3.9.0" and python_version < "3.14" \ +pyright==1.1.389 ; python_full_version >= "3.11.0" and python_version < "3.14" \ --hash=sha256:41e9620bba9254406dc1f621a88ceab5a88af4c826feb4f614d95691ed243a60 \ --hash=sha256:716bf8cc174ab8b4dcf6828c3298cac05c5ed775dda9910106a5dcfe4c7fe220 -pytest-asyncio==0.23.8 ; python_full_version >= "3.9.0" and python_version < "3.14" \ +pytest-asyncio==0.23.8 ; python_full_version >= "3.11.0" and python_version < "3.14" \ --hash=sha256:50265d892689a5faefb84df80819d1ecef566eb3549cf915dfb33569359d1ce2 \ --hash=sha256:759b10b33a6dc61cce40a8bd5205e302978bbbcc00e279a8b61d9a6a3c82e4d3 -pytest-cov==6.0.0 ; python_version >= "3.9" and python_version < "3.14" \ +pytest-cov==6.0.0 ; python_full_version >= "3.11.0" and python_version < "3.14" \ --hash=sha256:eee6f1b9e61008bd34975a4d5bab25801eb31898b032dd55addc93e96fcaaa35 \ --hash=sha256:fde0b595ca248bb8e2d76f020b465f3b107c9632e6a1d1705f17834c89dcadc0 -pytest-sugar==1.0.0 ; python_full_version >= "3.9.0" and python_version < "3.14" \ +pytest-sugar==1.0.0 ; python_full_version >= "3.11.0" and python_version < "3.14" \ --hash=sha256:6422e83258f5b0c04ce7c632176c7732cab5fdb909cb39cca5c9139f81276c0a \ --hash=sha256:70ebcd8fc5795dc457ff8b69d266a4e2e8a74ae0c3edc749381c64b5246c8dfd -pytest-timeout==2.3.1 ; python_full_version >= "3.9.0" and python_version < "3.14" \ +pytest-timeout==2.3.1 ; python_full_version >= "3.11.0" and python_version < "3.14" \ --hash=sha256:12397729125c6ecbdaca01035b9e5239d4db97352320af155b3f5de1ba5165d9 \ --hash=sha256:68188cb703edfc6a18fad98dc25a3c61e9f24d644b0b70f33af545219fc7813e -pytest-xdist==3.6.1 ; python_full_version >= "3.9.0" and python_version < "3.14" \ +pytest-xdist==3.6.1 ; python_full_version >= "3.11.0" and python_version < "3.14" \ --hash=sha256:9ed4adfb68a016610848639bb7e02c9352d5d9f03d04809919e2dafc3be4cca7 \ --hash=sha256:ead156a4db231eec769737f57668ef58a2084a34b2e55c4a8fa20d861107300d -pytest==7.4.0 ; python_version >= "3.9" and python_version < "3.14" \ +pytest==7.4.0 ; python_full_version >= "3.11.0" and python_version < "3.14" \ --hash=sha256:78bf16451a2eb8c7a2ea98e32dc119fd2aa758f1d5d66dbf0a59d69a3969df32 \ --hash=sha256:b4bf8c45bd59934ed84001ad51e11b4ee40d40a1229d2c79f9c592b0a3f6bd8a -python-dateutil==2.9.0.post0 ; python_full_version >= "3.9.0" and python_version < "3.14" \ +python-dateutil==2.9.0.post0 ; python_full_version >= "3.11.0" and python_version < "3.14" \ --hash=sha256:37dd54208da7e1cd875388217d5e00ebd4179249f90fb72437e91a35459a0ad3 \ --hash=sha256:a8b2bc7bffae282281c8140a97d3aa9c14da0b136dfe83f850eea9a5f7470427 -six==1.16.0 ; python_full_version >= "3.9.0" and python_version < "3.14" \ +six==1.16.0 ; python_full_version >= "3.11.0" and python_version < "3.14" \ --hash=sha256:1e61c37477a1626458e36f7b1d82aa5c9b094fa4802892072e49de9c60c4c926 \ --hash=sha256:8abb2f1d86890a2dfb989f9a77cfcfd3e47c2a354b01111771326f8aa26e0254 -termcolor==2.5.0 ; python_version >= "3.9" and python_version < "3.14" \ +termcolor==2.5.0 ; python_full_version >= "3.11.0" and python_version < "3.14" \ --hash=sha256:37b17b5fc1e604945c2642c872a3764b5d547a48009871aea3edd3afa180afb8 \ --hash=sha256:998d8d27da6d48442e8e1f016119076b690d962507531df4890fcd2db2ef8a6f -tomli==2.1.0 ; python_version >= "3.9" and python_version < "3.14" \ - --hash=sha256:3f646cae2aec94e17d04973e4249548320197cfabdf130015d023de4b74d8ab8 \ - --hash=sha256:a5c57c3d1c56f5ccdf89f6523458f60ef716e210fc47c4cfb188c5ba473e0391 -typing-extensions==4.12.2 ; python_version >= "3.9" and python_version < "3.14" \ +typing-extensions==4.12.2 ; python_full_version >= "3.11.0" and python_version < "3.14" \ --hash=sha256:04e5ca0351e0f3f85c6853954072df659d0d13fac324d0072316b67d7794700d \ --hash=sha256:1a7ead55c7e559dd4dee8856e3a88b41225abfe1ce8df57b7c13915fe121ffb8 -virtualenv==20.27.1 ; python_full_version >= "3.9.0" and python_version < "3.14" \ +virtualenv==20.27.1 ; python_full_version >= "3.11.0" and python_version < "3.14" \ --hash=sha256:142c6be10212543b32c6c45d3d3893dff89112cc588b7d0879ae5a1ec03a47ba \ --hash=sha256:f11f1b8a29525562925f745563bfd48b189450f61fb34c4f9cc79dd5aa32a1f4 -yarl==1.17.1 ; python_version >= "3.9" and python_version < "3.14" \ +yarl==1.17.1 ; python_full_version >= "3.11.0" and python_version < "3.14" \ --hash=sha256:06157fb3c58f2736a5e47c8fcbe1afc8b5de6fb28b14d25574af9e62150fcaac \ --hash=sha256:067a63fcfda82da6b198fa73079b1ca40b7c9b7994995b6ee38acda728b64d47 \ --hash=sha256:0b1794853124e2f663f0ea54efb0340b457f08d40a1cef78edfa086576179c91 \ From cfcb6daa1fdd69488d71f9395eac3d62c1064496 Mon Sep 17 00:00:00 2001 From: FasterSpeeding Date: Sun, 17 Nov 2024 01:45:54 +0000 Subject: [PATCH 06/14] Update README.md --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 577c1cf38..7d25d8d14 100644 --- a/README.md +++ b/README.md @@ -4,7 +4,7 @@ A flexible command framework designed to extend Hikari. # Installation -You can install Tanjun from PyPI using the following command in any Python 3.9 or above environment. +You can install Tanjun from PyPI using the following command in any Python 3.11 or above environment. ``` python -m pip install -U hikari-tanjun From 8173866c43b58eb1e7ec438defc64ac1be6f1748 Mon Sep 17 00:00:00 2001 From: Faster Speeding Date: Sun, 17 Nov 2024 15:49:30 +0000 Subject: [PATCH 07/14] Update code and docs --- CONTRIBUTING.md | 9 +- dev-requirements/tests.in | 2 - docs_src/usage.py | 10 +- examples/error_handling.py | 4 +- examples/impls.py | 6 +- examples/protos.py | 4 +- examples/slash_commands.py | 3 +- pyproject.toml | 10 - tanjun/_internal/__init__.py | 52 +- tanjun/_internal/cache.py | 2 +- tanjun/_internal/localisation.py | 16 +- tanjun/_internal/vendor/__init__.py | 12 - tanjun/_internal/vendor/inspect.py | 3313 ------------------ tanjun/_internal/vendor/inspect.py.LICENSE | 279 -- tanjun/_internal/vendor/inspect.pyi | 371 -- tanjun/_internal/vendor/inspect.pyi.LICENSE | 237 -- tanjun/abc.py | 560 ++- tanjun/annotations.py | 425 ++- tanjun/checks.py | 244 +- tanjun/clients.py | 512 ++- tanjun/commands/base.py | 13 +- tanjun/commands/menu.py | 118 +- tanjun/commands/message.py | 59 +- tanjun/commands/slash.py | 553 ++- tanjun/components.py | 113 +- tanjun/context/autocomplete.py | 28 +- tanjun/context/base.py | 26 +- tanjun/context/menu.py | 31 +- tanjun/context/message.py | 51 +- tanjun/context/slash.py | 181 +- tanjun/conversion.py | 40 +- tanjun/dependencies/async_cache.py | 8 +- tanjun/dependencies/callbacks.py | 4 +- tanjun/dependencies/data.py | 25 +- tanjun/dependencies/limiters.py | 110 +- tanjun/dependencies/locales.py | 13 +- tanjun/dependencies/owners.py | 12 +- tanjun/dependencies/reloaders.py | 49 +- tanjun/errors.py | 44 +- tanjun/hooks.py | 33 +- tanjun/parsing.py | 375 +- tanjun/permissions.py | 12 +- tanjun/schedules.py | 66 +- tests/commands/test_base.py | 2 +- tests/commands/test_menu.py | 22 +- tests/commands/test_message.py | 18 +- tests/commands/test_slash.py | 22 +- tests/context/test_base.py | 2 +- tests/context/test_message.py | 8 +- tests/context/test_slash.py | 12 +- tests/dependencies/test_data.py | 6 +- tests/dependencies/test_limiters.py | 6 +- tests/dependencies/test_owners.py | 7 +- tests/test_annotations.py | 506 ++- tests/test_annotations_future_annotations.py | 291 +- tests/test_checks.py | 2 +- tests/test_clients.py | 119 +- tests/test_clients_future_annotations.py | 68 +- tests/test_components.py | 68 +- tests/test_components_future_annotations.py | 82 +- tests/test_conversion.py | 24 +- tests/test_errors.py | 3 +- tests/test_hooks.py | 3 +- tests/test_injecting.py | 3 +- tests/test_schedules.py | 6 +- 65 files changed, 2370 insertions(+), 6945 deletions(-) delete mode 100644 tanjun/_internal/vendor/__init__.py delete mode 100644 tanjun/_internal/vendor/inspect.py delete mode 100644 tanjun/_internal/vendor/inspect.py.LICENSE delete mode 100644 tanjun/_internal/vendor/inspect.pyi delete mode 100644 tanjun/_internal/vendor/inspect.pyi.LICENSE diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index b7e1c1eee..3e56a62ea 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -33,12 +33,11 @@ and should also use styles which are specific to [pdoc](https://pdoc.dev/docs/pd A few examples of pdoc style would be: * Links: Unlike sphinx, regardless of whether you're linking to a module, class, function or variable the link will - always be in the style of `` `link.to.thing` `` with no type information included and relative links being supported - for types in the current module (e.g. `` `Class.attribute` ``. + always be in the style of `` [link.to.thing][] `` with no type information included. * Documenting fluent methods: The return type for fluent methods should be given as `Self` with the description for it following the lines of something like "the {x} instance to enable chained calls". -* Documented types (such as for parameters and return types) which are unions should be documented using `|` style - and `T | None`/`T | hikari.UndefinedType` are preferred over `typing.Optional[T]`/`hikari.UndefinedOr[T]` +* Union types sohuld be annotated in code and documentation using `|` style and `T | None`/`T | hikari.UndefinedType` + are preferred over `T | None`/`hikari.UndefinedOr[T]` ### CHANGELOG.md @@ -65,7 +64,7 @@ good references for how projects should be type-hinted to be `type-complete`. **NOTES** * This project deviates from the common convention of importing types from the typing module and instead - imports the typing module itself to use generics and types in it like `typing.Union` and `typing.Optional`. + imports the typing module itself to use generics and types in it like `typing.Annotated`. * Since this project supports python 3.9+, the `typing` types which were deprecated by [PEP 585](https://www.python.org/dev/peps/pep-0585/) should be avoided in favour of their `collections.abc`, builtin, `re` and `contextlib` equivalents. diff --git a/dev-requirements/tests.in b/dev-requirements/tests.in index 72a6554b7..781c199b4 100644 --- a/dev-requirements/tests.in +++ b/dev-requirements/tests.in @@ -2,8 +2,6 @@ -r ./constraints.in freezegun>=1.2.2 -# unittest.mock doesn't work with inspect.signature on all covered versions. -mock>=5.0.2 pytest-asyncio>=0.20.1 pytest-timeout>=2.1 pytest-xdist>=3.1 diff --git a/docs_src/usage.py b/docs_src/usage.py index 7c5e2bdea..885ad3096 100644 --- a/docs_src/usage.py +++ b/docs_src/usage.py @@ -161,7 +161,7 @@ def get_video(value: str) -> Video: ... def annotations_example() -> None: - from typing import Annotated, Optional + from typing import Annotated from tanjun.annotations import Bool, Converted, Int, Ranged, Str, User @@ -173,7 +173,7 @@ async def command( name: Annotated[Str, "description"], age: Annotated[Int, Ranged(13, 130), "an int option with a min, max of 13, 130"], video: Annotated[Video, Converted(get_video), "a required string option which is converted with get_video"], - user: Annotated[Optional[User], "a user option which defaults to None"] = None, + user: Annotated[User | None, "a user option which defaults to None"] = None, enabled: Annotated[Bool, "a bool option which defaults to True"] = True, ) -> None: ... @@ -195,7 +195,7 @@ def responding_to_commands_example() -> None: @tanjun.as_message_command("name") @tanjun.as_user_menu("name") async def command( - ctx: tanjun.abc.Context, user: typing.Annotated[typing.Optional[annotations.User], "The user to target"] = None + ctx: tanjun.abc.Context, user: typing.Annotated[annotations.User | None, "The user to target"] = None ) -> None: user = user or ctx.author message = await ctx.respond( @@ -226,7 +226,7 @@ def autocomplete_example(component: tanjun.Component) -> None: @tanjun.with_str_slash_option("opt1", "description") @tanjun.with_str_slash_option("opt2", "description", default=None) @tanjun.as_slash_command("name", "description") - async def slash_command(ctx: tanjun.abc.SlashContext, opt1: str, opt2: typing.Optional[str]) -> None: ... + async def slash_command(ctx: tanjun.abc.SlashContext, opt1: str, opt2: str | None) -> None: ... @slash_command.with_str_autocomplete("opt1") async def opt1_autocomplete(ctx: tanjun.abc.AutocompleteContext, value: str) -> None: @@ -323,7 +323,7 @@ async def success_hook(ctx: tanjun.abc.Context) -> None: ... def error_hook_example(hooks: tanjun.abc.AnyHooks) -> None: @hooks.with_on_error # hooks.add_on_error - async def error_hook(ctx: tanjun.abc.Context, error: Exception) -> typing.Optional[bool]: ... + async def error_hook(ctx: tanjun.abc.Context, error: Exception) -> bool | None: ... def parser_error_hook_example(hooks: tanjun.abc.AnyHooks) -> None: diff --git a/examples/error_handling.py b/examples/error_handling.py index 56d6a4279..ab651c708 100644 --- a/examples/error_handling.py +++ b/examples/error_handling.py @@ -9,8 +9,6 @@ # You should have received a copy of the CC0 Public Domain Dedication along with this software. # If not, see . """Examples of how hooks may be used within a bot with a focus on error handling.""" -import typing - import hikari import tanjun @@ -23,7 +21,7 @@ @hooks.with_on_error -async def on_error(ctx: tanjun.abc.Context, exc: Exception) -> typing.Optional[bool]: +async def on_error(ctx: tanjun.abc.Context, exc: Exception) -> bool | None: """General error handler. This will be called on all errors raised during execution except errors diff --git a/examples/impls.py b/examples/impls.py index 1fae8293b..9f96940de 100644 --- a/examples/impls.py +++ b/examples/impls.py @@ -22,15 +22,15 @@ async def connect_to_database(*args: typing.Any, **kwargs: typing.Any) -> typing class DatabaseImpl: def __init__(self) -> None: - self._conn: typing.Optional[typing.Any] = None + self._conn: typing.Any | None = None async def connect(self, config: examples.config.ExampleConfig = tanjun.inject(type=examples.config.ExampleConfig)): self._conn = await connect_to_database(password=config.database_password, url=config.database_url) - async def get_guild_info(self, guild_id: int) -> typing.Optional[protos.GuildConfig]: + async def get_guild_info(self, guild_id: int) -> protos.GuildConfig | None: raise NotImplementedError - async def get_user_info(self, user_id: int) -> typing.Optional[protos.UserInfo]: + async def get_user_info(self, user_id: int) -> protos.UserInfo | None: raise NotImplementedError async def remove_user(self, user_id: int) -> None: diff --git a/examples/protos.py b/examples/protos.py index df252e2de..99688dd37 100644 --- a/examples/protos.py +++ b/examples/protos.py @@ -22,10 +22,10 @@ class UserInfo(typing.Protocol): ... class DatabaseProto(typing.Protocol): - async def get_guild_info(self, guild_id: int) -> typing.Optional[GuildConfig]: + async def get_guild_info(self, guild_id: int) -> GuildConfig | None: raise NotImplementedError - async def get_user_info(self, user_id: int) -> typing.Optional[UserInfo]: + async def get_user_info(self, user_id: int) -> UserInfo | None: raise NotImplementedError async def remove_user(self, user_id: int) -> None: diff --git a/examples/slash_commands.py b/examples/slash_commands.py index 53071d565..ec44ba45b 100644 --- a/examples/slash_commands.py +++ b/examples/slash_commands.py @@ -25,7 +25,6 @@ # `tanjun.abc.SlashContext` to allow state to still be tracked and ensure # better compatibility. import asyncio -import typing import hikari @@ -58,7 +57,7 @@ async def nsfw_command(ctx: tanjun.abc.Context) -> None: # to the "name" argument as type str if it was provided else None. @tanjun.with_str_slash_option("name", "Option description", default=None) @nested_group.as_sub_command("hi", "command description") -async def hi_command(ctx: tanjun.abc.Context, name: typing.Optional[str], member: hikari.Member) -> None: +async def hi_command(ctx: tanjun.abc.Context, name: str | None, member: hikari.Member) -> None: if name: await ctx.respond(f"Hi, {name} and {member.username}") diff --git a/pyproject.toml b/pyproject.toml index 120d0d517..a090c3f20 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -39,7 +39,6 @@ Changelog = "https://tanjun.cursed.solutions/changelog" name = "tanjun" [tool.black] -extend-exclude = "^\\/tanjun\\/_internal\\/vendor\\/.*$" include = ".*pyi?$" line-length = 120 skip-magic-trailing-comma = true @@ -64,14 +63,12 @@ exclude_lines = [ "^\\s*@abc.abstractmethod$", "^if typing.TYPE_CHECKING:$" ] -omit = ["tanjun/_internal/vendor/*"] [tool.flake8] accept-encodings = "utf-8" count = true docstring-convention = "numpy" eradicate-aggressive = true -exclude = ["tanjun/_internal/vendor/**"] extend-select = ["TC100", "TC101"] force-future-annotations = true ignore-decorators = "overload" @@ -124,7 +121,6 @@ per-file-ignores = [ [tool.isort] profile = "black" force_single_line = true -skip = ["tanjun/_internal/vendor"] [tool.mypy] # some good strict settings @@ -143,9 +139,6 @@ warn_redundant_casts = false allow_redefinition = true disable_error_code = ["type-abstract"] -# Ignore vendored modules -exclude = ["tanjun/_internal/vendor/"] - [tool.piped] default_sessions = [ "reformat", @@ -158,7 +151,6 @@ default_sessions = [ "verify-types", ] extra_test_installs = ["."] -path_ignore = "tanjun\\/_internal\\/vendor\\/" project_name = "tanjun" top_level_targets = ["./docs_src", "./examples", "./noxfile.py", "./tanjun", "./tests"] @@ -183,7 +175,6 @@ python_versions = ["3.11", "3.12", "3.13", "3.14-dev"] exclude = "docs_src" [tool.pyright] -exclude = ["tanjun/_internal/vendor"] include = ["docs_src", "examples", "tanjun", "noxfile.py", "tests"] pythonVersion = "3.11" @@ -233,4 +224,3 @@ tanjun.clients:(_LoaderDescriptor|_UnloaderDescriptor) | tanjun.dependencies.reloaders:(_PathLoader|_ScanResult) | .*Proto """ -exclude-modules = "tanjun._internal.vendor" diff --git a/tanjun/_internal/__init__.py b/tanjun/_internal/__init__.py index bb4c829cb..125c7d970 100644 --- a/tanjun/_internal/__init__.py +++ b/tanjun/_internal/__init__.py @@ -37,10 +37,10 @@ import copy as copy_ import enum import functools +import inspect import itertools import logging import operator -import sys import types import typing from collections import abc as collections @@ -48,22 +48,16 @@ import hikari from .. import errors -from .vendor import inspect if typing.TYPE_CHECKING: - import typing_extensions - from .. import abc as tanjun _T = typing.TypeVar("_T") - _P = typing_extensions.ParamSpec("_P") + _P = typing.ParamSpec("_P") _ContextT = typing.TypeVar("_ContextT", bound=tanjun.Context) _CoroT = collections.Coroutine[typing.Any, typing.Any, _T] - _TreeT = dict[ - typing.Union[str, "_IndexKeys"], - typing.Union["_TreeT", list[tuple[list[str], tanjun.MessageCommand[typing.Any]]]], - ] + _TreeT = dict["str | _IndexKeys", "_TreeT | list[tuple[list[str], tanjun.MessageCommand[typing.Any]]]"] _KeyT = typing.TypeVar("_KeyT") @@ -71,11 +65,7 @@ _LOGGER = logging.getLogger("hikari.tanjun") -if sys.version_info >= (3, 10): - UnionTypes = frozenset((typing.Union, types.UnionType)) - -else: - UnionTypes = frozenset((typing.Union,)) +UnionTypes = frozenset((typing.Union, types.UnionType)) class _DefaultEnum(enum.Enum): @@ -158,7 +148,7 @@ def __len__(self) -> int: _KEYWORD_TYPES = {inspect.Parameter.KEYWORD_ONLY, inspect.Parameter.POSITIONAL_OR_KEYWORD} -def get_kwargs(callback: collections.Callable[..., typing.Any], /) -> typing.Union[list[str], None]: +def get_kwargs(callback: collections.Callable[..., typing.Any], /) -> list[str] | None: """Get a list of the keyword argument names for a callback. Parameters @@ -286,10 +276,10 @@ async def wrapper(*args: _P.args, **kwargs: _P.kwargs) -> _T: class _WrappedProto(typing.Protocol): - wrapped_command: typing.Optional[tanjun.ExecutableCommand[typing.Any]] + wrapped_command: tanjun.ExecutableCommand[typing.Any] | None -def _has_wrapped(value: typing.Any, /) -> typing_extensions.TypeGuard[_WrappedProto]: +def _has_wrapped(value: typing.Any, /) -> typing.TypeGuard[_WrappedProto]: try: value.wrapped_command @@ -359,7 +349,7 @@ def apply_to_wrapped( def flatten_options( - name: str, options: typing.Optional[collections.Sequence[_OptionT]], / + name: str, options: collections.Sequence[_OptionT] | None, / ) -> tuple[str, collections.Sequence[_OptionT]]: """Flatten the options of a slash/autocomplete interaction. @@ -411,7 +401,7 @@ def flatten_options( CHANNEL_TYPES[hikari.InteractionChannel] = CHANNEL_TYPES[hikari.PartialChannel] -def parse_channel_types(*channel_types: typing.Union[type[hikari.PartialChannel], int]) -> list[hikari.ChannelType]: +def parse_channel_types(*channel_types: type[hikari.PartialChannel] | int) -> list[hikari.ChannelType]: """Parse a channel types collection to a list of channel type integers.""" types_iter = itertools.chain.from_iterable( (hikari.ChannelType(type_),) if isinstance(type_, int) else CHANNEL_TYPES[type_] for type_ in channel_types @@ -446,8 +436,8 @@ def repr_channel(channel_type: hikari.ChannelType, /) -> str: def cmp_command( - cmd: typing.Union[hikari.PartialCommand, hikari.api.CommandBuilder], - other: typing.Union[hikari.PartialCommand, hikari.api.CommandBuilder, None], + cmd: hikari.PartialCommand | hikari.api.CommandBuilder, + other: hikari.PartialCommand | hikari.api.CommandBuilder | None, /, ) -> bool: """Compare application command objects and command builders.""" @@ -479,10 +469,8 @@ def cmp_command( def cmp_all_commands( - commands: collections.Collection[typing.Union[hikari.PartialCommand, hikari.api.CommandBuilder]], - other: collections.Mapping[ - tuple[hikari.CommandType, str], typing.Union[hikari.PartialCommand, hikari.api.CommandBuilder] - ], + commands: collections.Collection[hikari.PartialCommand | hikari.api.CommandBuilder], + other: collections.Mapping[tuple[hikari.CommandType, str], hikari.PartialCommand | hikari.api.CommandBuilder], /, ) -> bool: """Compare two sets of command objects/builders.""" @@ -504,9 +492,9 @@ def __init__( strict: bool, /, *, - commands: typing.Optional[list[tanjun.MessageCommand[typing.Any]]] = None, - names_to_commands: typing.Optional[dict[str, tuple[str, tanjun.MessageCommand[typing.Any]]]] = None, - search_tree: typing.Optional[_TreeT] = None, + commands: list[tanjun.MessageCommand[typing.Any]] | None = None, + names_to_commands: dict[str, tuple[str, tanjun.MessageCommand[typing.Any]]] | None = None, + search_tree: _TreeT | None = None, ) -> None: """Initialise a message command index. @@ -564,7 +552,7 @@ def add(self, command: tanjun.MessageCommand[typing.Any], /) -> bool: else: # strict indexes avoid using the search tree all together. # This needs to be explicitly typed for MyPy. - node: typing.Union[_TreeT, list[tuple[list[str], tanjun.MessageCommand[typing.Any]]]] + node: _TreeT | list[tuple[list[str], tanjun.MessageCommand[typing.Any]]] for name in filter(None, command.names): node = self.search_tree # The search tree is kept case-insensitive as a check against the actual name @@ -593,7 +581,7 @@ def add(self, command: tanjun.MessageCommand[typing.Any], /) -> bool: self.commands.append(command) return True - def copy(self, *, parent: typing.Optional[tanjun.MessageCommandGroup[typing.Any]] = None) -> MessageCommandIndex: + def copy(self, *, parent: tanjun.MessageCommandGroup[typing.Any] | None = None) -> MessageCommandIndex: """In-place copy the index and its contained commands. Parameters @@ -646,7 +634,7 @@ def find( return # This needs to be explicitly typed for MyPy. - node: typing.Union[_TreeT, list[tuple[list[str], tanjun.MessageCommand[typing.Any]]]] + node: _TreeT | list[tuple[list[str], tanjun.MessageCommand[typing.Any]]] node = self.search_tree segments: list[tuple[int, list[tuple[list[str], tanjun.MessageCommand[typing.Any]]]]] = [] split = content.split(" ") @@ -696,7 +684,7 @@ def remove(self, command: tanjun.MessageCommand[typing.Any], /) -> None: return # This needs to be explicitly typed for MyPy. - node: typing.Union[_TreeT, list[tuple[list[str], tanjun.MessageCommand[typing.Any]]]] + node: _TreeT | list[tuple[list[str], tanjun.MessageCommand[typing.Any]]] for name in filter(None, command.names): nodes: list[tuple[str, _TreeT]] = [] node = self.search_tree diff --git a/tanjun/_internal/cache.py b/tanjun/_internal/cache.py index a4053bc6a..1672107bb 100644 --- a/tanjun/_internal/cache.py +++ b/tanjun/_internal/cache.py @@ -70,7 +70,7 @@ async def get_perm_channel(client: tanjun.Client, channel_id: hikari.Snowflake, hikari.channels.PermissibleGuildChannel The permissible guild channel. """ - channel: typing.Optional[hikari.PartialChannel] # MyPy compat + channel: hikari.PartialChannel | None # MyPy compat if client.cache and (channel := client.cache.get_guild_channel(channel_id)): return channel diff --git a/tanjun/_internal/localisation.py b/tanjun/_internal/localisation.py index 73d497d40..d2738c304 100644 --- a/tanjun/_internal/localisation.py +++ b/tanjun/_internal/localisation.py @@ -43,8 +43,7 @@ if typing.TYPE_CHECKING: from collections import abc as collections - - from typing_extensions import Self + from typing import Self class MaybeLocalised: @@ -53,10 +52,7 @@ class MaybeLocalised: __slots__ = ("default_value", "_field_name", "id", "localised_values") def __init__( - self, - field_name: str, - field: typing.Union[str, collections.Mapping[str, str], collections.Iterable[tuple[str, str]]], - /, + self, field_name: str, field: str | collections.Mapping[str, str] | collections.Iterable[tuple[str, str]], / ) -> None: """Initialise an instance of MaybeLocalised. @@ -85,7 +81,7 @@ def __init__( self._field_name = field_name if isinstance(field, str): self.default_value = field - self.id: typing.Optional[str] = None + self.id: str | None = None self.localised_values: dict[str, str] = {} else: @@ -107,7 +103,7 @@ def _values(self) -> collections.Iterable[str]: def localise( self, ctx: tanjun.Context, - localiser: typing.Optional[dependencies.AbstractLocaliser], + localiser: dependencies.AbstractLocaliser | None, field_type: NamedFields, field_name: str, /, @@ -211,7 +207,7 @@ def assert_length(self, min_length: int, max_length: int, /) -> Self: } NamedFields = typing.Literal["check", "choice.name", "option.description", "option.name"] _UnnamedFields = typing.Literal["description", "name"] -_FieldType = typing.Union[NamedFields, _UnnamedFields] +_FieldType = NamedFields | _UnnamedFields @typing.overload @@ -231,7 +227,7 @@ def to_localise_id( def to_localise_id( - command_type: _CommandTypes, command_name: str, field_type: _FieldType, field_name: typing.Optional[str] = None, / + command_type: _CommandTypes, command_name: str, field_type: _FieldType, field_name: str | None = None, / ) -> str: """Generate an ID for a localised field. diff --git a/tanjun/_internal/vendor/__init__.py b/tanjun/_internal/vendor/__init__.py deleted file mode 100644 index 6ba125e67..000000000 --- a/tanjun/_internal/vendor/__init__.py +++ /dev/null @@ -1,12 +0,0 @@ -from __future__ import annotations - -__all__ = ["inspect"] - -import sys - - -if sys.version_info >= (3, 10): - import inspect - -else: - from . import inspect diff --git a/tanjun/_internal/vendor/inspect.py b/tanjun/_internal/vendor/inspect.py deleted file mode 100644 index 0822db27c..000000000 --- a/tanjun/_internal/vendor/inspect.py +++ /dev/null @@ -1,3313 +0,0 @@ -# See ./inspect.py.LICENSE for the general license this falls under. - -# Vendored from https://github.com/python/cpython/blob/83aef4d34022f293336f606dba8598cc7ac8f9f2/Lib/inspect.py (3.10) -"""Get useful information from live Python objects. - -This module encapsulates the interface provided by the internal special -attributes (co_*, im_*, tb_*, etc.) in a friendlier fashion. -It also provides some help for examining source code and class layout. - -Here are some of the useful functions provided by this module: - - ismodule(), isclass(), ismethod(), isfunction(), isgeneratorfunction(), - isgenerator(), istraceback(), isframe(), iscode(), isbuiltin(), - isroutine() - check object types - getmembers() - get members of an object that satisfy a given condition - - getfile(), getsourcefile(), getsource() - find an object's source code - getdoc(), getcomments() - get documentation on an object - getmodule() - determine the module that an object came from - getclasstree() - arrange classes so as to represent their hierarchy - - getargvalues(), getcallargs() - get info about function arguments - getfullargspec() - same, with support for Python 3 features - formatargvalues() - format an argument spec - getouterframes(), getinnerframes() - get info about frames - currentframe() - get the current stack frame - stack(), trace() - get info about frames on the stack or in a traceback - - signature() - get a Signature object for the callable - - get_annotations() - safely compute an object's annotations -""" - -# This module is in the public domain. No warranties. - -__author__ = ('Ka-Ping Yee ', - 'Yury Selivanov ') - -import abc -import ast -import dis -import collections.abc -import enum -import importlib.machinery -import itertools -import linecache -import os -import re -import sys -import tokenize -import token -import types -import warnings -import functools -import builtins -from operator import attrgetter -from collections import namedtuple, OrderedDict - -# Create constants for the compiler flags in Include/code.h -# We try to get them from dis to avoid duplication -mod_dict = globals() -for k, v in dis.COMPILER_FLAG_NAMES.items(): - mod_dict["CO_" + v] = k - -# See Include/object.h -TPFLAGS_IS_ABSTRACT = 1 << 20 - - -def get_annotations(obj, *, globals=None, locals=None, eval_str=False): - """Compute the annotations dict for an object. - - obj may be a callable, class, or module. - Passing in an object of any other type raises TypeError. - - Returns a dict. get_annotations() returns a new dict every time - it's called; calling it twice on the same object will return two - different but equivalent dicts. - - This function handles several details for you: - - * If eval_str is true, values of type str will - be un-stringized using eval(). This is intended - for use with stringized annotations - ("from __future__ import annotations"). - * If obj doesn't have an annotations dict, returns an - empty dict. (Functions and methods always have an - annotations dict; classes, modules, and other types of - callables may not.) - * Ignores inherited annotations on classes. If a class - doesn't have its own annotations dict, returns an empty dict. - * All accesses to object members and dict values are done - using getattr() and dict.get() for safety. - * Always, always, always returns a freshly-created dict. - - eval_str controls whether or not values of type str are replaced - with the result of calling eval() on those values: - - * If eval_str is true, eval() is called on values of type str. - * If eval_str is false (the default), values of type str are unchanged. - - globals and locals are passed in to eval(); see the documentation - for eval() for more information. If either globals or locals is - None, this function may replace that value with a context-specific - default, contingent on type(obj): - - * If obj is a module, globals defaults to obj.__dict__. - * If obj is a class, globals defaults to - sys.modules[obj.__module__].__dict__ and locals - defaults to the obj class namespace. - * If obj is a callable, globals defaults to obj.__globals__, - although if obj is a wrapped function (using - functools.update_wrapper()) it is first unwrapped. - """ - if isinstance(obj, type): - # class - obj_dict = getattr(obj, '__dict__', None) - if obj_dict and hasattr(obj_dict, 'get'): - ann = obj_dict.get('__annotations__', None) - if isinstance(ann, types.GetSetDescriptorType): - ann = None - else: - ann = None - - obj_globals = None - module_name = getattr(obj, '__module__', None) - if module_name: - module = sys.modules.get(module_name, None) - if module: - obj_globals = getattr(module, '__dict__', None) - obj_locals = dict(vars(obj)) - unwrap = obj - elif isinstance(obj, types.ModuleType): - # module - ann = getattr(obj, '__annotations__', None) - obj_globals = getattr(obj, '__dict__') - obj_locals = None - unwrap = None - elif callable(obj): - # this includes types.Function, types.BuiltinFunctionType, - # types.BuiltinMethodType, functools.partial, functools.singledispatch, - # "class funclike" from Lib/test/test_inspect... on and on it goes. - ann = getattr(obj, '__annotations__', None) - obj_globals = getattr(obj, '__globals__', None) - obj_locals = None - unwrap = obj - else: - raise TypeError(f"{obj!r} is not a module, class, or callable.") - - if ann is None: - return {} - - if not isinstance(ann, dict): - raise ValueError(f"{obj!r}.__annotations__ is neither a dict nor None") - - if not ann: - return {} - - if not eval_str: - return dict(ann) - - if unwrap is not None: - while True: - if hasattr(unwrap, '__wrapped__'): - unwrap = unwrap.__wrapped__ - continue - if isinstance(unwrap, functools.partial): - unwrap = unwrap.func - continue - break - if hasattr(unwrap, "__globals__"): - obj_globals = unwrap.__globals__ - - if globals is None: - globals = obj_globals - if locals is None: - locals = obj_locals - - return_value = {key: - value if not isinstance(value, str) else eval(value, globals, locals) - for key, value in ann.items() } - return return_value - - -# ----------------------------------------------------------- type-checking -def ismodule(object): - """Return true if the object is a module. - - Module objects provide these attributes: - __cached__ pathname to byte compiled file - __doc__ documentation string - __file__ filename (missing for built-in modules)""" - return isinstance(object, types.ModuleType) - -def isclass(object): - """Return true if the object is a class. - - Class objects provide these attributes: - __doc__ documentation string - __module__ name of module in which this class was defined""" - return isinstance(object, type) - -def ismethod(object): - """Return true if the object is an instance method. - - Instance method objects provide these attributes: - __doc__ documentation string - __name__ name with which this method was defined - __func__ function object containing implementation of method - __self__ instance to which this method is bound""" - return isinstance(object, types.MethodType) - -def ismethoddescriptor(object): - """Return true if the object is a method descriptor. - - But not if ismethod() or isclass() or isfunction() are true. - - This is new in Python 2.2, and, for example, is true of int.__add__. - An object passing this test has a __get__ attribute but not a __set__ - attribute, but beyond that the set of attributes varies. __name__ is - usually sensible, and __doc__ often is. - - Methods implemented via descriptors that also pass one of the other - tests return false from the ismethoddescriptor() test, simply because - the other tests promise more -- you can, e.g., count on having the - __func__ attribute (etc) when an object passes ismethod().""" - if isclass(object) or ismethod(object) or isfunction(object): - # mutual exclusion - return False - tp = type(object) - return hasattr(tp, "__get__") and not hasattr(tp, "__set__") - -def isdatadescriptor(object): - """Return true if the object is a data descriptor. - - Data descriptors have a __set__ or a __delete__ attribute. Examples are - properties (defined in Python) and getsets and members (defined in C). - Typically, data descriptors will also have __name__ and __doc__ attributes - (properties, getsets, and members have both of these attributes), but this - is not guaranteed.""" - if isclass(object) or ismethod(object) or isfunction(object): - # mutual exclusion - return False - tp = type(object) - return hasattr(tp, "__set__") or hasattr(tp, "__delete__") - -if hasattr(types, 'MemberDescriptorType'): - # CPython and equivalent - def ismemberdescriptor(object): - """Return true if the object is a member descriptor. - - Member descriptors are specialized descriptors defined in extension - modules.""" - return isinstance(object, types.MemberDescriptorType) -else: - # Other implementations - def ismemberdescriptor(object): - """Return true if the object is a member descriptor. - - Member descriptors are specialized descriptors defined in extension - modules.""" - return False - -if hasattr(types, 'GetSetDescriptorType'): - # CPython and equivalent - def isgetsetdescriptor(object): - """Return true if the object is a getset descriptor. - - getset descriptors are specialized descriptors defined in extension - modules.""" - return isinstance(object, types.GetSetDescriptorType) -else: - # Other implementations - def isgetsetdescriptor(object): - """Return true if the object is a getset descriptor. - - getset descriptors are specialized descriptors defined in extension - modules.""" - return False - -def isfunction(object): - """Return true if the object is a user-defined function. - - Function objects provide these attributes: - __doc__ documentation string - __name__ name with which this function was defined - __code__ code object containing compiled function bytecode - __defaults__ tuple of any default values for arguments - __globals__ global namespace in which this function was defined - __annotations__ dict of parameter annotations - __kwdefaults__ dict of keyword only parameters with defaults""" - return isinstance(object, types.FunctionType) - -def _has_code_flag(f, flag): - """Return true if ``f`` is a function (or a method or functools.partial - wrapper wrapping a function) whose code object has the given ``flag`` - set in its flags.""" - while ismethod(f): - f = f.__func__ - f = functools._unwrap_partial(f) - if not isfunction(f): - return False - return bool(f.__code__.co_flags & flag) - -def isgeneratorfunction(obj): - """Return true if the object is a user-defined generator function. - - Generator function objects provide the same attributes as functions. - See help(isfunction) for a list of attributes.""" - return _has_code_flag(obj, CO_GENERATOR) - -def iscoroutinefunction(obj): - """Return true if the object is a coroutine function. - - Coroutine functions are defined with "async def" syntax. - """ - return _has_code_flag(obj, CO_COROUTINE) - -def isasyncgenfunction(obj): - """Return true if the object is an asynchronous generator function. - - Asynchronous generator functions are defined with "async def" - syntax and have "yield" expressions in their body. - """ - return _has_code_flag(obj, CO_ASYNC_GENERATOR) - -def isasyncgen(object): - """Return true if the object is an asynchronous generator.""" - return isinstance(object, types.AsyncGeneratorType) - -def isgenerator(object): - """Return true if the object is a generator. - - Generator objects provide these attributes: - __iter__ defined to support iteration over container - close raises a new GeneratorExit exception inside the - generator to terminate the iteration - gi_code code object - gi_frame frame object or possibly None once the generator has - been exhausted - gi_running set to 1 when generator is executing, 0 otherwise - next return the next item from the container - send resumes the generator and "sends" a value that becomes - the result of the current yield-expression - throw used to raise an exception inside the generator""" - return isinstance(object, types.GeneratorType) - -def iscoroutine(object): - """Return true if the object is a coroutine.""" - return isinstance(object, types.CoroutineType) - -def isawaitable(object): - """Return true if object can be passed to an ``await`` expression.""" - return (isinstance(object, types.CoroutineType) or - isinstance(object, types.GeneratorType) and - bool(object.gi_code.co_flags & CO_ITERABLE_COROUTINE) or - isinstance(object, collections.abc.Awaitable)) - -def istraceback(object): - """Return true if the object is a traceback. - - Traceback objects provide these attributes: - tb_frame frame object at this level - tb_lasti index of last attempted instruction in bytecode - tb_lineno current line number in Python source code - tb_next next inner traceback object (called by this level)""" - return isinstance(object, types.TracebackType) - -def isframe(object): - """Return true if the object is a frame object. - - Frame objects provide these attributes: - f_back next outer frame object (this frame's caller) - f_builtins built-in namespace seen by this frame - f_code code object being executed in this frame - f_globals global namespace seen by this frame - f_lasti index of last attempted instruction in bytecode - f_lineno current line number in Python source code - f_locals local namespace seen by this frame - f_trace tracing function for this frame, or None""" - return isinstance(object, types.FrameType) - -def iscode(object): - """Return true if the object is a code object. - - Code objects provide these attributes: - co_argcount number of arguments (not including *, ** args - or keyword only arguments) - co_code string of raw compiled bytecode - co_cellvars tuple of names of cell variables - co_consts tuple of constants used in the bytecode - co_filename name of file in which this code object was created - co_firstlineno number of first line in Python source code - co_flags bitmap: 1=optimized | 2=newlocals | 4=*arg | 8=**arg - | 16=nested | 32=generator | 64=nofree | 128=coroutine - | 256=iterable_coroutine | 512=async_generator - co_freevars tuple of names of free variables - co_posonlyargcount number of positional only arguments - co_kwonlyargcount number of keyword only arguments (not including ** arg) - co_lnotab encoded mapping of line numbers to bytecode indices - co_name name with which this code object was defined - co_names tuple of names other than arguments and function locals - co_nlocals number of local variables - co_stacksize virtual machine stack space required - co_varnames tuple of names of arguments and local variables""" - return isinstance(object, types.CodeType) - -def isbuiltin(object): - """Return true if the object is a built-in function or method. - - Built-in functions and methods provide these attributes: - __doc__ documentation string - __name__ original name of this function or method - __self__ instance to which a method is bound, or None""" - return isinstance(object, types.BuiltinFunctionType) - -def isroutine(object): - """Return true if the object is any kind of function or method.""" - return (isbuiltin(object) - or isfunction(object) - or ismethod(object) - or ismethoddescriptor(object)) - -def isabstract(object): - """Return true if the object is an abstract base class (ABC).""" - if not isinstance(object, type): - return False - if object.__flags__ & TPFLAGS_IS_ABSTRACT: - return True - if not issubclass(type(object), abc.ABCMeta): - return False - if hasattr(object, '__abstractmethods__'): - # It looks like ABCMeta.__new__ has finished running; - # TPFLAGS_IS_ABSTRACT should have been accurate. - return False - # It looks like ABCMeta.__new__ has not finished running yet; we're - # probably in __init_subclass__. We'll look for abstractmethods manually. - for name, value in object.__dict__.items(): - if getattr(value, "__isabstractmethod__", False): - return True - for base in object.__bases__: - for name in getattr(base, "__abstractmethods__", ()): - value = getattr(object, name, None) - if getattr(value, "__isabstractmethod__", False): - return True - return False - -def getmembers(object, predicate=None): - """Return all members of an object as (name, value) pairs sorted by name. - Optionally, only return members that satisfy a given predicate.""" - if isclass(object): - mro = (object,) + getmro(object) - else: - mro = () - results = [] - processed = set() - names = dir(object) - # :dd any DynamicClassAttributes to the list of names if object is a class; - # this may result in duplicate entries if, for example, a virtual - # attribute with the same name as a DynamicClassAttribute exists - try: - for base in object.__bases__: - for k, v in base.__dict__.items(): - if isinstance(v, types.DynamicClassAttribute): - names.append(k) - except AttributeError: - pass - for key in names: - # First try to get the value via getattr. Some descriptors don't - # like calling their __get__ (see bug #1785), so fall back to - # looking in the __dict__. - try: - value = getattr(object, key) - # handle the duplicate key - if key in processed: - raise AttributeError - except AttributeError: - for base in mro: - if key in base.__dict__: - value = base.__dict__[key] - break - else: - # could be a (currently) missing slot member, or a buggy - # __dir__; discard and move on - continue - if not predicate or predicate(value): - results.append((key, value)) - processed.add(key) - results.sort(key=lambda pair: pair[0]) - return results - -Attribute = namedtuple('Attribute', 'name kind defining_class object') - -def classify_class_attrs(cls): - """Return list of attribute-descriptor tuples. - - For each name in dir(cls), the return list contains a 4-tuple - with these elements: - - 0. The name (a string). - - 1. The kind of attribute this is, one of these strings: - 'class method' created via classmethod() - 'static method' created via staticmethod() - 'property' created via property() - 'method' any other flavor of method or descriptor - 'data' not a method - - 2. The class which defined this attribute (a class). - - 3. The object as obtained by calling getattr; if this fails, or if the - resulting object does not live anywhere in the class' mro (including - metaclasses) then the object is looked up in the defining class's - dict (found by walking the mro). - - If one of the items in dir(cls) is stored in the metaclass it will now - be discovered and not have None be listed as the class in which it was - defined. Any items whose home class cannot be discovered are skipped. - """ - - mro = getmro(cls) - metamro = getmro(type(cls)) # for attributes stored in the metaclass - metamro = tuple(cls for cls in metamro if cls not in (type, object)) - class_bases = (cls,) + mro - all_bases = class_bases + metamro - names = dir(cls) - # :dd any DynamicClassAttributes to the list of names; - # this may result in duplicate entries if, for example, a virtual - # attribute with the same name as a DynamicClassAttribute exists. - for base in mro: - for k, v in base.__dict__.items(): - if isinstance(v, types.DynamicClassAttribute) and v.fget is not None: - names.append(k) - result = [] - processed = set() - - for name in names: - # Get the object associated with the name, and where it was defined. - # Normal objects will be looked up with both getattr and directly in - # its class' dict (in case getattr fails [bug #1785], and also to look - # for a docstring). - # For DynamicClassAttributes on the second pass we only look in the - # class's dict. - # - # Getting an obj from the __dict__ sometimes reveals more than - # using getattr. Static and class methods are dramatic examples. - homecls = None - get_obj = None - dict_obj = None - if name not in processed: - try: - if name == '__dict__': - raise Exception("__dict__ is special, don't want the proxy") - get_obj = getattr(cls, name) - except Exception as exc: - pass - else: - homecls = getattr(get_obj, "__objclass__", homecls) - if homecls not in class_bases: - # if the resulting object does not live somewhere in the - # mro, drop it and search the mro manually - homecls = None - last_cls = None - # first look in the classes - for srch_cls in class_bases: - srch_obj = getattr(srch_cls, name, None) - if srch_obj is get_obj: - last_cls = srch_cls - # then check the metaclasses - for srch_cls in metamro: - try: - srch_obj = srch_cls.__getattr__(cls, name) - except AttributeError: - continue - if srch_obj is get_obj: - last_cls = srch_cls - if last_cls is not None: - homecls = last_cls - for base in all_bases: - if name in base.__dict__: - dict_obj = base.__dict__[name] - if homecls not in metamro: - homecls = base - break - if homecls is None: - # unable to locate the attribute anywhere, most likely due to - # buggy custom __dir__; discard and move on - continue - obj = get_obj if get_obj is not None else dict_obj - # Classify the object or its descriptor. - if isinstance(dict_obj, (staticmethod, types.BuiltinMethodType)): - kind = "static method" - obj = dict_obj - elif isinstance(dict_obj, (classmethod, types.ClassMethodDescriptorType)): - kind = "class method" - obj = dict_obj - elif isinstance(dict_obj, property): - kind = "property" - obj = dict_obj - elif isroutine(obj): - kind = "method" - else: - kind = "data" - result.append(Attribute(name, kind, homecls, obj)) - processed.add(name) - return result - -# ----------------------------------------------------------- class helpers - -def getmro(cls): - "Return tuple of base classes (including cls) in method resolution order." - return cls.__mro__ - -# -------------------------------------------------------- function helpers - -def unwrap(func, *, stop=None): - """Get the object wrapped by *func*. - - Follows the chain of :attr:`__wrapped__` attributes returning the last - object in the chain. - - *stop* is an optional callback accepting an object in the wrapper chain - as its sole argument that allows the unwrapping to be terminated early if - the callback returns a true value. If the callback never returns a true - value, the last object in the chain is returned as usual. For example, - :func:`signature` uses this to stop unwrapping if any object in the - chain has a ``__signature__`` attribute defined. - - :exc:`ValueError` is raised if a cycle is encountered. - - """ - if stop is None: - def _is_wrapper(f): - return hasattr(f, '__wrapped__') - else: - def _is_wrapper(f): - return hasattr(f, '__wrapped__') and not stop(f) - f = func # remember the original func for error reporting - # Memoise by id to tolerate non-hashable objects, but store objects to - # ensure they aren't destroyed, which would allow their IDs to be reused. - memo = {id(f): f} - recursion_limit = sys.getrecursionlimit() - while _is_wrapper(func): - func = func.__wrapped__ - id_func = id(func) - if (id_func in memo) or (len(memo) >= recursion_limit): - raise ValueError('wrapper loop when unwrapping {!r}'.format(f)) - memo[id_func] = func - return func - -# -------------------------------------------------- source code extraction -def indentsize(line): - """Return the indent size, in spaces, at the start of a line of text.""" - expline = line.expandtabs() - return len(expline) - len(expline.lstrip()) - -def _findclass(func): - cls = sys.modules.get(func.__module__) - if cls is None: - return None - for name in func.__qualname__.split('.')[:-1]: - cls = getattr(cls, name) - if not isclass(cls): - return None - return cls - -def _finddoc(obj): - if isclass(obj): - for base in obj.__mro__: - if base is not object: - try: - doc = base.__doc__ - except AttributeError: - continue - if doc is not None: - return doc - return None - - if ismethod(obj): - name = obj.__func__.__name__ - self = obj.__self__ - if (isclass(self) and - getattr(getattr(self, name, None), '__func__') is obj.__func__): - # classmethod - cls = self - else: - cls = self.__class__ - elif isfunction(obj): - name = obj.__name__ - cls = _findclass(obj) - if cls is None or getattr(cls, name) is not obj: - return None - elif isbuiltin(obj): - name = obj.__name__ - self = obj.__self__ - if (isclass(self) and - self.__qualname__ + '.' + name == obj.__qualname__): - # classmethod - cls = self - else: - cls = self.__class__ - # Should be tested before isdatadescriptor(). - elif isinstance(obj, property): - func = obj.fget - name = func.__name__ - cls = _findclass(func) - if cls is None or getattr(cls, name) is not obj: - return None - elif ismethoddescriptor(obj) or isdatadescriptor(obj): - name = obj.__name__ - cls = obj.__objclass__ - if getattr(cls, name) is not obj: - return None - if ismemberdescriptor(obj): - slots = getattr(cls, '__slots__', None) - if isinstance(slots, dict) and name in slots: - return slots[name] - else: - return None - for base in cls.__mro__: - try: - doc = getattr(base, name).__doc__ - except AttributeError: - continue - if doc is not None: - return doc - return None - -def getdoc(object): - """Get the documentation string for an object. - - All tabs are expanded to spaces. To clean up docstrings that are - indented to line up with blocks of code, any whitespace than can be - uniformly removed from the second line onwards is removed.""" - try: - doc = object.__doc__ - except AttributeError: - return None - if doc is None: - try: - doc = _finddoc(object) - except (AttributeError, TypeError): - return None - if not isinstance(doc, str): - return None - return cleandoc(doc) - -def cleandoc(doc): - """Clean up indentation from docstrings. - - Any whitespace that can be uniformly removed from the second line - onwards is removed.""" - try: - lines = doc.expandtabs().split('\n') - except UnicodeError: - return None - else: - # Find minimum indentation of any non-blank lines after first line. - margin = sys.maxsize - for line in lines[1:]: - content = len(line.lstrip()) - if content: - indent = len(line) - content - margin = min(margin, indent) - # Remove indentation. - if lines: - lines[0] = lines[0].lstrip() - if margin < sys.maxsize: - for i in range(1, len(lines)): lines[i] = lines[i][margin:] - # Remove any trailing or leading blank lines. - while lines and not lines[-1]: - lines.pop() - while lines and not lines[0]: - lines.pop(0) - return '\n'.join(lines) - -def getfile(object): - """Work out which source or compiled file an object was defined in.""" - if ismodule(object): - if getattr(object, '__file__', None): - return object.__file__ - raise TypeError('{!r} is a built-in module'.format(object)) - if isclass(object): - if hasattr(object, '__module__'): - module = sys.modules.get(object.__module__) - if getattr(module, '__file__', None): - return module.__file__ - if object.__module__ == '__main__': - raise OSError('source code not available') - raise TypeError('{!r} is a built-in class'.format(object)) - if ismethod(object): - object = object.__func__ - if isfunction(object): - object = object.__code__ - if istraceback(object): - object = object.tb_frame - if isframe(object): - object = object.f_code - if iscode(object): - return object.co_filename - raise TypeError('module, class, method, function, traceback, frame, or ' - 'code object was expected, got {}'.format( - type(object).__name__)) - -def getmodulename(path): - """Return the module name for a given file, or None.""" - fname = os.path.basename(path) - # Check for paths that look like an actual module file - suffixes = [(-len(suffix), suffix) - for suffix in importlib.machinery.all_suffixes()] - suffixes.sort() # try longest suffixes first, in case they overlap - for neglen, suffix in suffixes: - if fname.endswith(suffix): - return fname[:neglen] - return None - -def getsourcefile(object): - """Return the filename that can be used to locate an object's source. - Return None if no way can be identified to get the source. - """ - filename = getfile(object) - all_bytecode_suffixes = importlib.machinery.DEBUG_BYTECODE_SUFFIXES[:] - all_bytecode_suffixes += importlib.machinery.OPTIMIZED_BYTECODE_SUFFIXES[:] - if any(filename.endswith(s) for s in all_bytecode_suffixes): - filename = (os.path.splitext(filename)[0] + - importlib.machinery.SOURCE_SUFFIXES[0]) - elif any(filename.endswith(s) for s in - importlib.machinery.EXTENSION_SUFFIXES): - return None - if os.path.exists(filename): - return filename - # only return a non-existent filename if the module has a PEP 302 loader - module = getmodule(object, filename) - if getattr(module, '__loader__', None) is not None: - return filename - elif getattr(getattr(module, "__spec__", None), "loader", None) is not None: - return filename - # or it is in the linecache - elif filename in linecache.cache: - return filename - -def getabsfile(object, _filename=None): - """Return an absolute path to the source or compiled file for an object. - - The idea is for each object to have a unique origin, so this routine - normalizes the result as much as possible.""" - if _filename is None: - _filename = getsourcefile(object) or getfile(object) - return os.path.normcase(os.path.abspath(_filename)) - -modulesbyfile = {} -_filesbymodname = {} - -def getmodule(object, _filename=None): - """Return the module an object was defined in, or None if not found.""" - if ismodule(object): - return object - if hasattr(object, '__module__'): - return sys.modules.get(object.__module__) - # Try the filename to modulename cache - if _filename is not None and _filename in modulesbyfile: - return sys.modules.get(modulesbyfile[_filename]) - # Try the cache again with the absolute file name - try: - file = getabsfile(object, _filename) - except (TypeError, FileNotFoundError): - return None - if file in modulesbyfile: - return sys.modules.get(modulesbyfile[file]) - # Update the filename to module name cache and check yet again - # Copy sys.modules in order to cope with changes while iterating - for modname, module in sys.modules.copy().items(): - if ismodule(module) and hasattr(module, '__file__'): - f = module.__file__ - if f == _filesbymodname.get(modname, None): - # Have already mapped this module, so skip it - continue - _filesbymodname[modname] = f - f = getabsfile(module) - # Always map to the name the module knows itself by - modulesbyfile[f] = modulesbyfile[ - os.path.realpath(f)] = module.__name__ - if file in modulesbyfile: - return sys.modules.get(modulesbyfile[file]) - # Check the main module - main = sys.modules['__main__'] - if not hasattr(object, '__name__'): - return None - if hasattr(main, object.__name__): - mainobject = getattr(main, object.__name__) - if mainobject is object: - return main - # Check builtins - builtin = sys.modules['builtins'] - if hasattr(builtin, object.__name__): - builtinobject = getattr(builtin, object.__name__) - if builtinobject is object: - return builtin - - -class ClassFoundException(Exception): - pass - - -class _ClassFinder(ast.NodeVisitor): - - def __init__(self, qualname): - self.stack = [] - self.qualname = qualname - - def visit_FunctionDef(self, node): - self.stack.append(node.name) - self.stack.append('') - self.generic_visit(node) - self.stack.pop() - self.stack.pop() - - visit_AsyncFunctionDef = visit_FunctionDef - - def visit_ClassDef(self, node): - self.stack.append(node.name) - if self.qualname == '.'.join(self.stack): - # Return the decorator for the class if present - if node.decorator_list: - line_number = node.decorator_list[0].lineno - else: - line_number = node.lineno - - # decrement by one since lines starts with indexing by zero - line_number -= 1 - raise ClassFoundException(line_number) - self.generic_visit(node) - self.stack.pop() - - -def findsource(object): - """Return the entire source file and starting line number for an object. - - The argument may be a module, class, method, function, traceback, frame, - or code object. The source code is returned as a list of all the lines - in the file and the line number indexes a line in that list. An OSError - is raised if the source code cannot be retrieved.""" - - file = getsourcefile(object) - if file: - # Invalidate cache if needed. - linecache.checkcache(file) - else: - file = getfile(object) - # Allow filenames in form of "" to pass through. - # `doctest` monkeypatches `linecache` module to enable - # inspection, so let `linecache.getlines` to be called. - if not (file.startswith('<') and file.endswith('>')): - raise OSError('source code not available') - - module = getmodule(object, file) - if module: - lines = linecache.getlines(file, module.__dict__) - else: - lines = linecache.getlines(file) - if not lines: - raise OSError('could not get source code') - - if ismodule(object): - return lines, 0 - - if isclass(object): - qualname = object.__qualname__ - source = ''.join(lines) - tree = ast.parse(source) - class_finder = _ClassFinder(qualname) - try: - class_finder.visit(tree) - except ClassFoundException as e: - line_number = e.args[0] - return lines, line_number - else: - raise OSError('could not find class definition') - - if ismethod(object): - object = object.__func__ - if isfunction(object): - object = object.__code__ - if istraceback(object): - object = object.tb_frame - if isframe(object): - object = object.f_code - if iscode(object): - if not hasattr(object, 'co_firstlineno'): - raise OSError('could not find function definition') - lnum = object.co_firstlineno - 1 - pat = re.compile(r'^(\s*def\s)|(\s*async\s+def\s)|(.*(? 0: - try: - line = lines[lnum] - except IndexError: - raise OSError('lineno is out of bounds') - if pat.match(line): - break - lnum = lnum - 1 - return lines, lnum - raise OSError('could not find code object') - -def getcomments(object): - """Get lines of comments immediately preceding an object's source code. - - Returns None when source can't be found. - """ - try: - lines, lnum = findsource(object) - except (OSError, TypeError): - return None - - if ismodule(object): - # Look for a comment block at the top of the file. - start = 0 - if lines and lines[0][:2] == '#!': start = 1 - while start < len(lines) and lines[start].strip() in ('', '#'): - start = start + 1 - if start < len(lines) and lines[start][:1] == '#': - comments = [] - end = start - while end < len(lines) and lines[end][:1] == '#': - comments.append(lines[end].expandtabs()) - end = end + 1 - return ''.join(comments) - - # Look for a preceding block of comments at the same indentation. - elif lnum > 0: - indent = indentsize(lines[lnum]) - end = lnum - 1 - if end >= 0 and lines[end].lstrip()[:1] == '#' and \ - indentsize(lines[end]) == indent: - comments = [lines[end].expandtabs().lstrip()] - if end > 0: - end = end - 1 - comment = lines[end].expandtabs().lstrip() - while comment[:1] == '#' and indentsize(lines[end]) == indent: - comments[:0] = [comment] - end = end - 1 - if end < 0: break - comment = lines[end].expandtabs().lstrip() - while comments and comments[0].strip() == '#': - comments[:1] = [] - while comments and comments[-1].strip() == '#': - comments[-1:] = [] - return ''.join(comments) - -class EndOfBlock(Exception): pass - -class BlockFinder: - """Provide a tokeneater() method to detect the end of a code block.""" - def __init__(self): - self.indent = 0 - self.islambda = False - self.started = False - self.passline = False - self.indecorator = False - self.decoratorhasargs = False - self.last = 1 - self.body_col0 = None - - def tokeneater(self, type, token, srowcol, erowcol, line): - if not self.started and not self.indecorator: - # skip any decorators - if token == "@": - self.indecorator = True - # look for the first "def", "class" or "lambda" - elif token in ("def", "class", "lambda"): - if token == "lambda": - self.islambda = True - self.started = True - self.passline = True # skip to the end of the line - elif token == "(": - if self.indecorator: - self.decoratorhasargs = True - elif token == ")": - if self.indecorator: - self.indecorator = False - self.decoratorhasargs = False - elif type == tokenize.NEWLINE: - self.passline = False # stop skipping when a NEWLINE is seen - self.last = srowcol[0] - if self.islambda: # lambdas always end at the first NEWLINE - raise EndOfBlock - # hitting a NEWLINE when in a decorator without args - # ends the decorator - if self.indecorator and not self.decoratorhasargs: - self.indecorator = False - elif self.passline: - pass - elif type == tokenize.INDENT: - if self.body_col0 is None and self.started: - self.body_col0 = erowcol[1] - self.indent = self.indent + 1 - self.passline = True - elif type == tokenize.DEDENT: - self.indent = self.indent - 1 - # the end of matching indent/dedent pairs end a block - # (note that this only works for "def"/"class" blocks, - # not e.g. for "if: else:" or "try: finally:" blocks) - if self.indent <= 0: - raise EndOfBlock - elif type == tokenize.COMMENT: - if self.body_col0 is not None and srowcol[1] >= self.body_col0: - # Include comments if indented at least as much as the block - self.last = srowcol[0] - elif self.indent == 0 and type not in (tokenize.COMMENT, tokenize.NL): - # any other token on the same indentation level end the previous - # block as well, except the pseudo-tokens COMMENT and NL. - raise EndOfBlock - -def getblock(lines): - """Extract the block of code at the top of the given list of lines.""" - blockfinder = BlockFinder() - try: - tokens = tokenize.generate_tokens(iter(lines).__next__) - for _token in tokens: - blockfinder.tokeneater(*_token) - except (EndOfBlock, IndentationError): - pass - return lines[:blockfinder.last] - -def getsourcelines(object): - """Return a list of source lines and starting line number for an object. - - The argument may be a module, class, method, function, traceback, frame, - or code object. The source code is returned as a list of the lines - corresponding to the object and the line number indicates where in the - original source file the first line of code was found. An OSError is - raised if the source code cannot be retrieved.""" - object = unwrap(object) - lines, lnum = findsource(object) - - if istraceback(object): - object = object.tb_frame - - # for module or frame that corresponds to module, return all source lines - if (ismodule(object) or - (isframe(object) and object.f_code.co_name == "")): - return lines, 0 - else: - return getblock(lines[lnum:]), lnum + 1 - -def getsource(object): - """Return the text of the source code for an object. - - The argument may be a module, class, method, function, traceback, frame, - or code object. The source code is returned as a single string. An - OSError is raised if the source code cannot be retrieved.""" - lines, lnum = getsourcelines(object) - return ''.join(lines) - -# --------------------------------------------------- class tree extraction -def walktree(classes, children, parent): - """Recursive helper function for getclasstree().""" - results = [] - classes.sort(key=attrgetter('__module__', '__name__')) - for c in classes: - results.append((c, c.__bases__)) - if c in children: - results.append(walktree(children[c], children, c)) - return results - -def getclasstree(classes, unique=False): - """Arrange the given list of classes into a hierarchy of nested lists. - - Where a nested list appears, it contains classes derived from the class - whose entry immediately precedes the list. Each entry is a 2-tuple - containing a class and a tuple of its base classes. If the 'unique' - argument is true, exactly one entry appears in the returned structure - for each class in the given list. Otherwise, classes using multiple - inheritance and their descendants will appear multiple times.""" - children = {} - roots = [] - for c in classes: - if c.__bases__: - for parent in c.__bases__: - if parent not in children: - children[parent] = [] - if c not in children[parent]: - children[parent].append(c) - if unique and parent in classes: break - elif c not in roots: - roots.append(c) - for parent in children: - if parent not in classes: - roots.append(parent) - return walktree(roots, children, None) - -# ------------------------------------------------ argument list extraction -Arguments = namedtuple('Arguments', 'args, varargs, varkw') - -def getargs(co): - """Get information about the arguments accepted by a code object. - - Three things are returned: (args, varargs, varkw), where - 'args' is the list of argument names. Keyword-only arguments are - appended. 'varargs' and 'varkw' are the names of the * and ** - arguments or None.""" - if not iscode(co): - raise TypeError('{!r} is not a code object'.format(co)) - - names = co.co_varnames - nargs = co.co_argcount - nkwargs = co.co_kwonlyargcount - args = list(names[:nargs]) - kwonlyargs = list(names[nargs:nargs+nkwargs]) - step = 0 - - nargs += nkwargs - varargs = None - if co.co_flags & CO_VARARGS: - varargs = co.co_varnames[nargs] - nargs = nargs + 1 - varkw = None - if co.co_flags & CO_VARKEYWORDS: - varkw = co.co_varnames[nargs] - return Arguments(args + kwonlyargs, varargs, varkw) - -ArgSpec = namedtuple('ArgSpec', 'args varargs keywords defaults') - -def getargspec(func): - """Get the names and default values of a function's parameters. - - A tuple of four things is returned: (args, varargs, keywords, defaults). - 'args' is a list of the argument names, including keyword-only argument names. - 'varargs' and 'keywords' are the names of the * and ** parameters or None. - 'defaults' is an n-tuple of the default values of the last n parameters. - - This function is deprecated, as it does not support annotations or - keyword-only parameters and will raise ValueError if either is present - on the supplied callable. - - For a more structured introspection API, use inspect.signature() instead. - - Alternatively, use getfullargspec() for an API with a similar namedtuple - based interface, but full support for annotations and keyword-only - parameters. - - Deprecated since Python 3.5, use `inspect.getfullargspec()`. - """ - warnings.warn("inspect.getargspec() is deprecated since Python 3.0, " - "use inspect.signature() or inspect.getfullargspec()", - DeprecationWarning, stacklevel=2) - args, varargs, varkw, defaults, kwonlyargs, kwonlydefaults, ann = \ - getfullargspec(func) - if kwonlyargs or ann: - raise ValueError("Function has keyword-only parameters or annotations" - ", use inspect.signature() API which can support them") - return ArgSpec(args, varargs, varkw, defaults) - -FullArgSpec = namedtuple('FullArgSpec', - 'args, varargs, varkw, defaults, kwonlyargs, kwonlydefaults, annotations') - -def getfullargspec(func): - """Get the names and default values of a callable object's parameters. - - A tuple of seven things is returned: - (args, varargs, varkw, defaults, kwonlyargs, kwonlydefaults, annotations). - 'args' is a list of the parameter names. - 'varargs' and 'varkw' are the names of the * and ** parameters or None. - 'defaults' is an n-tuple of the default values of the last n parameters. - 'kwonlyargs' is a list of keyword-only parameter names. - 'kwonlydefaults' is a dictionary mapping names from kwonlyargs to defaults. - 'annotations' is a dictionary mapping parameter names to annotations. - - Notable differences from inspect.signature(): - - the "self" parameter is always reported, even for bound methods - - wrapper chains defined by __wrapped__ *not* unwrapped automatically - """ - try: - # Re: `skip_bound_arg=False` - # - # There is a notable difference in behaviour between getfullargspec - # and Signature: the former always returns 'self' parameter for bound - # methods, whereas the Signature always shows the actual calling - # signature of the passed object. - # - # To simulate this behaviour, we "unbind" bound methods, to trick - # inspect.signature to always return their first parameter ("self", - # usually) - - # Re: `follow_wrapper_chains=False` - # - # getfullargspec() historically ignored __wrapped__ attributes, - # so we ensure that remains the case in 3.3+ - - sig = _signature_from_callable(func, - follow_wrapper_chains=False, - skip_bound_arg=False, - sigcls=Signature, - eval_str=False) - except Exception as ex: - # Most of the times 'signature' will raise ValueError. - # But, it can also raise AttributeError, and, maybe something - # else. So to be fully backwards compatible, we catch all - # possible exceptions here, and reraise a TypeError. - raise TypeError('unsupported callable') from ex - - args = [] - varargs = None - varkw = None - posonlyargs = [] - kwonlyargs = [] - annotations = {} - defaults = () - kwdefaults = {} - - if sig.return_annotation is not sig.empty: - annotations['return'] = sig.return_annotation - - for param in sig.parameters.values(): - kind = param.kind - name = param.name - - if kind is _POSITIONAL_ONLY: - posonlyargs.append(name) - if param.default is not param.empty: - defaults += (param.default,) - elif kind is _POSITIONAL_OR_KEYWORD: - args.append(name) - if param.default is not param.empty: - defaults += (param.default,) - elif kind is _VAR_POSITIONAL: - varargs = name - elif kind is _KEYWORD_ONLY: - kwonlyargs.append(name) - if param.default is not param.empty: - kwdefaults[name] = param.default - elif kind is _VAR_KEYWORD: - varkw = name - - if param.annotation is not param.empty: - annotations[name] = param.annotation - - if not kwdefaults: - # compatibility with 'func.__kwdefaults__' - kwdefaults = None - - if not defaults: - # compatibility with 'func.__defaults__' - defaults = None - - return FullArgSpec(posonlyargs + args, varargs, varkw, defaults, - kwonlyargs, kwdefaults, annotations) - - -ArgInfo = namedtuple('ArgInfo', 'args varargs keywords locals') - -def getargvalues(frame): - """Get information about arguments passed into a particular frame. - - A tuple of four things is returned: (args, varargs, varkw, locals). - 'args' is a list of the argument names. - 'varargs' and 'varkw' are the names of the * and ** arguments or None. - 'locals' is the locals dictionary of the given frame.""" - args, varargs, varkw = getargs(frame.f_code) - return ArgInfo(args, varargs, varkw, frame.f_locals) - -def formatannotation(annotation, base_module=None): - if getattr(annotation, '__module__', None) == 'typing': - return repr(annotation).replace('typing.', '') - if isinstance(annotation, types.GenericAlias): - return str(annotation) - if isinstance(annotation, type): - if annotation.__module__ in ('builtins', base_module): - return annotation.__qualname__ - return annotation.__module__+'.'+annotation.__qualname__ - return repr(annotation) - -def formatannotationrelativeto(object): - module = getattr(object, '__module__', None) - def _formatannotation(annotation): - return formatannotation(annotation, module) - return _formatannotation - -def formatargspec(args, varargs=None, varkw=None, defaults=None, - kwonlyargs=(), kwonlydefaults={}, annotations={}, - formatarg=str, - formatvarargs=lambda name: '*' + name, - formatvarkw=lambda name: '**' + name, - formatvalue=lambda value: '=' + repr(value), - formatreturns=lambda text: ' -> ' + text, - formatannotation=formatannotation): - """Format an argument spec from the values returned by getfullargspec. - - The first seven arguments are (args, varargs, varkw, defaults, - kwonlyargs, kwonlydefaults, annotations). The other five arguments - are the corresponding optional formatting functions that are called to - turn names and values into strings. The last argument is an optional - function to format the sequence of arguments. - - Deprecated since Python 3.5: use the `signature` function and `Signature` - objects. - """ - - from warnings import warn - - warn("`formatargspec` is deprecated since Python 3.5. Use `signature` and " - "the `Signature` object directly", - DeprecationWarning, - stacklevel=2) - - def formatargandannotation(arg): - result = formatarg(arg) - if arg in annotations: - result += ': ' + formatannotation(annotations[arg]) - return result - specs = [] - if defaults: - firstdefault = len(args) - len(defaults) - for i, arg in enumerate(args): - spec = formatargandannotation(arg) - if defaults and i >= firstdefault: - spec = spec + formatvalue(defaults[i - firstdefault]) - specs.append(spec) - if varargs is not None: - specs.append(formatvarargs(formatargandannotation(varargs))) - else: - if kwonlyargs: - specs.append('*') - if kwonlyargs: - for kwonlyarg in kwonlyargs: - spec = formatargandannotation(kwonlyarg) - if kwonlydefaults and kwonlyarg in kwonlydefaults: - spec += formatvalue(kwonlydefaults[kwonlyarg]) - specs.append(spec) - if varkw is not None: - specs.append(formatvarkw(formatargandannotation(varkw))) - result = '(' + ', '.join(specs) + ')' - if 'return' in annotations: - result += formatreturns(formatannotation(annotations['return'])) - return result - -def formatargvalues(args, varargs, varkw, locals, - formatarg=str, - formatvarargs=lambda name: '*' + name, - formatvarkw=lambda name: '**' + name, - formatvalue=lambda value: '=' + repr(value)): - """Format an argument spec from the 4 values returned by getargvalues. - - The first four arguments are (args, varargs, varkw, locals). The - next four arguments are the corresponding optional formatting functions - that are called to turn names and values into strings. The ninth - argument is an optional function to format the sequence of arguments.""" - def convert(name, locals=locals, - formatarg=formatarg, formatvalue=formatvalue): - return formatarg(name) + formatvalue(locals[name]) - specs = [] - for i in range(len(args)): - specs.append(convert(args[i])) - if varargs: - specs.append(formatvarargs(varargs) + formatvalue(locals[varargs])) - if varkw: - specs.append(formatvarkw(varkw) + formatvalue(locals[varkw])) - return '(' + ', '.join(specs) + ')' - -def _missing_arguments(f_name, argnames, pos, values): - names = [repr(name) for name in argnames if name not in values] - missing = len(names) - if missing == 1: - s = names[0] - elif missing == 2: - s = "{} and {}".format(*names) - else: - tail = ", {} and {}".format(*names[-2:]) - del names[-2:] - s = ", ".join(names) + tail - raise TypeError("%s() missing %i required %s argument%s: %s" % - (f_name, missing, - "positional" if pos else "keyword-only", - "" if missing == 1 else "s", s)) - -def _too_many(f_name, args, kwonly, varargs, defcount, given, values): - atleast = len(args) - defcount - kwonly_given = len([arg for arg in kwonly if arg in values]) - if varargs: - plural = atleast != 1 - sig = "at least %d" % (atleast,) - elif defcount: - plural = True - sig = "from %d to %d" % (atleast, len(args)) - else: - plural = len(args) != 1 - sig = str(len(args)) - kwonly_sig = "" - if kwonly_given: - msg = " positional argument%s (and %d keyword-only argument%s)" - kwonly_sig = (msg % ("s" if given != 1 else "", kwonly_given, - "s" if kwonly_given != 1 else "")) - raise TypeError("%s() takes %s positional argument%s but %d%s %s given" % - (f_name, sig, "s" if plural else "", given, kwonly_sig, - "was" if given == 1 and not kwonly_given else "were")) - -def getcallargs(func, /, *positional, **named): - """Get the mapping of arguments to values. - - A dict is returned, with keys the function argument names (including the - names of the * and ** arguments, if any), and values the respective bound - values from 'positional' and 'named'.""" - spec = getfullargspec(func) - args, varargs, varkw, defaults, kwonlyargs, kwonlydefaults, ann = spec - f_name = func.__name__ - arg2value = {} - - - if ismethod(func) and func.__self__ is not None: - # implicit 'self' (or 'cls' for classmethods) argument - positional = (func.__self__,) + positional - num_pos = len(positional) - num_args = len(args) - num_defaults = len(defaults) if defaults else 0 - - n = min(num_pos, num_args) - for i in range(n): - arg2value[args[i]] = positional[i] - if varargs: - arg2value[varargs] = tuple(positional[n:]) - possible_kwargs = set(args + kwonlyargs) - if varkw: - arg2value[varkw] = {} - for kw, value in named.items(): - if kw not in possible_kwargs: - if not varkw: - raise TypeError("%s() got an unexpected keyword argument %r" % - (f_name, kw)) - arg2value[varkw][kw] = value - continue - if kw in arg2value: - raise TypeError("%s() got multiple values for argument %r" % - (f_name, kw)) - arg2value[kw] = value - if num_pos > num_args and not varargs: - _too_many(f_name, args, kwonlyargs, varargs, num_defaults, - num_pos, arg2value) - if num_pos < num_args: - req = args[:num_args - num_defaults] - for arg in req: - if arg not in arg2value: - _missing_arguments(f_name, req, True, arg2value) - for i, arg in enumerate(args[num_args - num_defaults:]): - if arg not in arg2value: - arg2value[arg] = defaults[i] - missing = 0 - for kwarg in kwonlyargs: - if kwarg not in arg2value: - if kwonlydefaults and kwarg in kwonlydefaults: - arg2value[kwarg] = kwonlydefaults[kwarg] - else: - missing += 1 - if missing: - _missing_arguments(f_name, kwonlyargs, False, arg2value) - return arg2value - -ClosureVars = namedtuple('ClosureVars', 'nonlocals globals builtins unbound') - -def getclosurevars(func): - """ - Get the mapping of free variables to their current values. - - Returns a named tuple of dicts mapping the current nonlocal, global - and builtin references as seen by the body of the function. A final - set of unbound names that could not be resolved is also provided. - """ - - if ismethod(func): - func = func.__func__ - - if not isfunction(func): - raise TypeError("{!r} is not a Python function".format(func)) - - code = func.__code__ - # Nonlocal references are named in co_freevars and resolved - # by looking them up in __closure__ by positional index - if func.__closure__ is None: - nonlocal_vars = {} - else: - nonlocal_vars = { - var : cell.cell_contents - for var, cell in zip(code.co_freevars, func.__closure__) - } - - # Global and builtin references are named in co_names and resolved - # by looking them up in __globals__ or __builtins__ - global_ns = func.__globals__ - builtin_ns = global_ns.get("__builtins__", builtins.__dict__) - if ismodule(builtin_ns): - builtin_ns = builtin_ns.__dict__ - global_vars = {} - builtin_vars = {} - unbound_names = set() - for name in code.co_names: - if name in ("None", "True", "False"): - # Because these used to be builtins instead of keywords, they - # may still show up as name references. We ignore them. - continue - try: - global_vars[name] = global_ns[name] - except KeyError: - try: - builtin_vars[name] = builtin_ns[name] - except KeyError: - unbound_names.add(name) - - return ClosureVars(nonlocal_vars, global_vars, - builtin_vars, unbound_names) - -# -------------------------------------------------- stack frame extraction - -Traceback = namedtuple('Traceback', 'filename lineno function code_context index') - -def getframeinfo(frame, context=1): - """Get information about a frame or traceback object. - - A tuple of five things is returned: the filename, the line number of - the current line, the function name, a list of lines of context from - the source code, and the index of the current line within that list. - The optional second argument specifies the number of lines of context - to return, which are centered around the current line.""" - if istraceback(frame): - lineno = frame.tb_lineno - frame = frame.tb_frame - else: - lineno = frame.f_lineno - if not isframe(frame): - raise TypeError('{!r} is not a frame or traceback object'.format(frame)) - - filename = getsourcefile(frame) or getfile(frame) - if context > 0: - start = lineno - 1 - context//2 - try: - lines, lnum = findsource(frame) - except OSError: - lines = index = None - else: - start = max(0, min(start, len(lines) - context)) - lines = lines[start:start+context] - index = lineno - 1 - start - else: - lines = index = None - - return Traceback(filename, lineno, frame.f_code.co_name, lines, index) - -def getlineno(frame): - """Get the line number from a frame object, allowing for optimization.""" - # FrameType.f_lineno is now a descriptor that grovels co_lnotab - return frame.f_lineno - -FrameInfo = namedtuple('FrameInfo', ('frame',) + Traceback._fields) - -def getouterframes(frame, context=1): - """Get a list of records for a frame and all higher (calling) frames. - - Each record contains a frame object, filename, line number, function - name, a list of lines of context, and index within the context.""" - framelist = [] - while frame: - frameinfo = (frame,) + getframeinfo(frame, context) - framelist.append(FrameInfo(*frameinfo)) - frame = frame.f_back - return framelist - -def getinnerframes(tb, context=1): - """Get a list of records for a traceback's frame and all lower frames. - - Each record contains a frame object, filename, line number, function - name, a list of lines of context, and index within the context.""" - framelist = [] - while tb: - frameinfo = (tb.tb_frame,) + getframeinfo(tb, context) - framelist.append(FrameInfo(*frameinfo)) - tb = tb.tb_next - return framelist - -def currentframe(): - """Return the frame of the caller or None if this is not possible.""" - return sys._getframe(1) if hasattr(sys, "_getframe") else None - -def stack(context=1): - """Return a list of records for the stack above the caller's frame.""" - return getouterframes(sys._getframe(1), context) - -def trace(context=1): - """Return a list of records for the stack below the current exception.""" - return getinnerframes(sys.exc_info()[2], context) - - -# ------------------------------------------------ static version of getattr - -_sentinel = object() - -def _static_getmro(klass): - return type.__dict__['__mro__'].__get__(klass) - -def _check_instance(obj, attr): - instance_dict = {} - try: - instance_dict = object.__getattribute__(obj, "__dict__") - except AttributeError: - pass - return dict.get(instance_dict, attr, _sentinel) - - -def _check_class(klass, attr): - for entry in _static_getmro(klass): - if _shadowed_dict(type(entry)) is _sentinel: - try: - return entry.__dict__[attr] - except KeyError: - pass - return _sentinel - -def _is_type(obj): - try: - _static_getmro(obj) - except TypeError: - return False - return True - -def _shadowed_dict(klass): - dict_attr = type.__dict__["__dict__"] - for entry in _static_getmro(klass): - try: - class_dict = dict_attr.__get__(entry)["__dict__"] - except KeyError: - pass - else: - if not (type(class_dict) is types.GetSetDescriptorType and - class_dict.__name__ == "__dict__" and - class_dict.__objclass__ is entry): - return class_dict - return _sentinel - -def getattr_static(obj, attr, default=_sentinel): - """Retrieve attributes without triggering dynamic lookup via the - descriptor protocol, __getattr__ or __getattribute__. - - Note: this function may not be able to retrieve all attributes - that getattr can fetch (like dynamically created attributes) - and may find attributes that getattr can't (like descriptors - that raise AttributeError). It can also return descriptor objects - instead of instance members in some cases. See the - documentation for details. - """ - instance_result = _sentinel - if not _is_type(obj): - klass = type(obj) - dict_attr = _shadowed_dict(klass) - if (dict_attr is _sentinel or - type(dict_attr) is types.MemberDescriptorType): - instance_result = _check_instance(obj, attr) - else: - klass = obj - - klass_result = _check_class(klass, attr) - - if instance_result is not _sentinel and klass_result is not _sentinel: - if (_check_class(type(klass_result), '__get__') is not _sentinel and - _check_class(type(klass_result), '__set__') is not _sentinel): - return klass_result - - if instance_result is not _sentinel: - return instance_result - if klass_result is not _sentinel: - return klass_result - - if obj is klass: - # for types we check the metaclass too - for entry in _static_getmro(type(klass)): - if _shadowed_dict(type(entry)) is _sentinel: - try: - return entry.__dict__[attr] - except KeyError: - pass - if default is not _sentinel: - return default - raise AttributeError(attr) - - -# ------------------------------------------------ generator introspection - -GEN_CREATED = 'GEN_CREATED' -GEN_RUNNING = 'GEN_RUNNING' -GEN_SUSPENDED = 'GEN_SUSPENDED' -GEN_CLOSED = 'GEN_CLOSED' - -def getgeneratorstate(generator): - """Get current state of a generator-iterator. - - Possible states are: - GEN_CREATED: Waiting to start execution. - GEN_RUNNING: Currently being executed by the interpreter. - GEN_SUSPENDED: Currently suspended at a yield expression. - GEN_CLOSED: Execution has completed. - """ - if generator.gi_running: - return GEN_RUNNING - if generator.gi_frame is None: - return GEN_CLOSED - if generator.gi_frame.f_lasti == -1: - return GEN_CREATED - return GEN_SUSPENDED - - -def getgeneratorlocals(generator): - """ - Get the mapping of generator local variables to their current values. - - A dict is returned, with the keys the local variable names and values the - bound values.""" - - if not isgenerator(generator): - raise TypeError("{!r} is not a Python generator".format(generator)) - - frame = getattr(generator, "gi_frame", None) - if frame is not None: - return generator.gi_frame.f_locals - else: - return {} - - -# ------------------------------------------------ coroutine introspection - -CORO_CREATED = 'CORO_CREATED' -CORO_RUNNING = 'CORO_RUNNING' -CORO_SUSPENDED = 'CORO_SUSPENDED' -CORO_CLOSED = 'CORO_CLOSED' - -def getcoroutinestate(coroutine): - """Get current state of a coroutine object. - - Possible states are: - CORO_CREATED: Waiting to start execution. - CORO_RUNNING: Currently being executed by the interpreter. - CORO_SUSPENDED: Currently suspended at an await expression. - CORO_CLOSED: Execution has completed. - """ - if coroutine.cr_running: - return CORO_RUNNING - if coroutine.cr_frame is None: - return CORO_CLOSED - if coroutine.cr_frame.f_lasti == -1: - return CORO_CREATED - return CORO_SUSPENDED - - -def getcoroutinelocals(coroutine): - """ - Get the mapping of coroutine local variables to their current values. - - A dict is returned, with the keys the local variable names and values the - bound values.""" - frame = getattr(coroutine, "cr_frame", None) - if frame is not None: - return frame.f_locals - else: - return {} - - -############################################################################### -### Function Signature Object (PEP 362) -############################################################################### - - -_WrapperDescriptor = type(type.__call__) -_MethodWrapper = type(all.__call__) -_ClassMethodWrapper = type(int.__dict__['from_bytes']) - -_NonUserDefinedCallables = (_WrapperDescriptor, - _MethodWrapper, - _ClassMethodWrapper, - types.BuiltinFunctionType) - - -def _signature_get_user_defined_method(cls, method_name): - """Private helper. Checks if ``cls`` has an attribute - named ``method_name`` and returns it only if it is a - pure python function. - """ - try: - meth = getattr(cls, method_name) - except AttributeError: - return - else: - if not isinstance(meth, _NonUserDefinedCallables): - # Once '__signature__' will be added to 'C'-level - # callables, this check won't be necessary - return meth - - -def _signature_get_partial(wrapped_sig, partial, extra_args=()): - """Private helper to calculate how 'wrapped_sig' signature will - look like after applying a 'functools.partial' object (or alike) - on it. - """ - - old_params = wrapped_sig.parameters - new_params = OrderedDict(old_params.items()) - - partial_args = partial.args or () - partial_keywords = partial.keywords or {} - - if extra_args: - partial_args = extra_args + partial_args - - try: - ba = wrapped_sig.bind_partial(*partial_args, **partial_keywords) - except TypeError as ex: - msg = 'partial object {!r} has incorrect arguments'.format(partial) - raise ValueError(msg) from ex - - - transform_to_kwonly = False - for param_name, param in old_params.items(): - try: - arg_value = ba.arguments[param_name] - except KeyError: - pass - else: - if param.kind is _POSITIONAL_ONLY: - # If positional-only parameter is bound by partial, - # it effectively disappears from the signature - new_params.pop(param_name) - continue - - if param.kind is _POSITIONAL_OR_KEYWORD: - if param_name in partial_keywords: - # This means that this parameter, and all parameters - # after it should be keyword-only (and var-positional - # should be removed). Here's why. Consider the following - # function: - # foo(a, b, *args, c): - # pass - # - # "partial(foo, a='spam')" will have the following - # signature: "(*, a='spam', b, c)". Because attempting - # to call that partial with "(10, 20)" arguments will - # raise a TypeError, saying that "a" argument received - # multiple values. - transform_to_kwonly = True - # Set the new default value - new_params[param_name] = param.replace(default=arg_value) - else: - # was passed as a positional argument - new_params.pop(param.name) - continue - - if param.kind is _KEYWORD_ONLY: - # Set the new default value - new_params[param_name] = param.replace(default=arg_value) - - if transform_to_kwonly: - assert param.kind is not _POSITIONAL_ONLY - - if param.kind is _POSITIONAL_OR_KEYWORD: - new_param = new_params[param_name].replace(kind=_KEYWORD_ONLY) - new_params[param_name] = new_param - new_params.move_to_end(param_name) - elif param.kind in (_KEYWORD_ONLY, _VAR_KEYWORD): - new_params.move_to_end(param_name) - elif param.kind is _VAR_POSITIONAL: - new_params.pop(param.name) - - return wrapped_sig.replace(parameters=new_params.values()) - - -def _signature_bound_method(sig): - """Private helper to transform signatures for unbound - functions to bound methods. - """ - - params = tuple(sig.parameters.values()) - - if not params or params[0].kind in (_VAR_KEYWORD, _KEYWORD_ONLY): - raise ValueError('invalid method signature') - - kind = params[0].kind - if kind in (_POSITIONAL_OR_KEYWORD, _POSITIONAL_ONLY): - # Drop first parameter: - # '(p1, p2[, ...])' -> '(p2[, ...])' - params = params[1:] - else: - if kind is not _VAR_POSITIONAL: - # Unless we add a new parameter type we never - # get here - raise ValueError('invalid argument type') - # It's a var-positional parameter. - # Do nothing. '(*args[, ...])' -> '(*args[, ...])' - - return sig.replace(parameters=params) - - -def _signature_is_builtin(obj): - """Private helper to test if `obj` is a callable that might - support Argument Clinic's __text_signature__ protocol. - """ - return (isbuiltin(obj) or - ismethoddescriptor(obj) or - isinstance(obj, _NonUserDefinedCallables) or - # Can't test 'isinstance(type)' here, as it would - # also be True for regular python classes - obj in (type, object)) - - -def _signature_is_functionlike(obj): - """Private helper to test if `obj` is a duck type of FunctionType. - A good example of such objects are functions compiled with - Cython, which have all attributes that a pure Python function - would have, but have their code statically compiled. - """ - - if not callable(obj) or isclass(obj): - # All function-like objects are obviously callables, - # and not classes. - return False - - name = getattr(obj, '__name__', None) - code = getattr(obj, '__code__', None) - defaults = getattr(obj, '__defaults__', _void) # Important to use _void ... - kwdefaults = getattr(obj, '__kwdefaults__', _void) # ... and not None here - annotations = getattr(obj, '__annotations__', None) - - return (isinstance(code, types.CodeType) and - isinstance(name, str) and - (defaults is None or isinstance(defaults, tuple)) and - (kwdefaults is None or isinstance(kwdefaults, dict)) and - (isinstance(annotations, (dict)) or annotations is None) ) - - -def _signature_get_bound_param(spec): - """ Private helper to get first parameter name from a - __text_signature__ of a builtin method, which should - be in the following format: '($param1, ...)'. - Assumptions are that the first argument won't have - a default value or an annotation. - """ - - assert spec.startswith('($') - - pos = spec.find(',') - if pos == -1: - pos = spec.find(')') - - cpos = spec.find(':') - assert cpos == -1 or cpos > pos - - cpos = spec.find('=') - assert cpos == -1 or cpos > pos - - return spec[2:pos] - - -def _signature_strip_non_python_syntax(signature): - """ - Private helper function. Takes a signature in Argument Clinic's - extended signature format. - - Returns a tuple of three things: - * that signature re-rendered in standard Python syntax, - * the index of the "self" parameter (generally 0), or None if - the function does not have a "self" parameter, and - * the index of the last "positional only" parameter, - or None if the signature has no positional-only parameters. - """ - - if not signature: - return signature, None, None - - self_parameter = None - last_positional_only = None - - lines = [l.encode('ascii') for l in signature.split('\n')] - generator = iter(lines).__next__ - token_stream = tokenize.tokenize(generator) - - delayed_comma = False - skip_next_comma = False - text = [] - add = text.append - - current_parameter = 0 - OP = token.OP - ERRORTOKEN = token.ERRORTOKEN - - # token stream always starts with ENCODING token, skip it - t = next(token_stream) - assert t.type == tokenize.ENCODING - - for t in token_stream: - type, string = t.type, t.string - - if type == OP: - if string == ',': - if skip_next_comma: - skip_next_comma = False - else: - assert not delayed_comma - delayed_comma = True - current_parameter += 1 - continue - - if string == '/': - assert not skip_next_comma - assert last_positional_only is None - skip_next_comma = True - last_positional_only = current_parameter - 1 - continue - - if (type == ERRORTOKEN) and (string == '$'): - assert self_parameter is None - self_parameter = current_parameter - continue - - if delayed_comma: - delayed_comma = False - if not ((type == OP) and (string == ')')): - add(', ') - add(string) - if (string == ','): - add(' ') - clean_signature = ''.join(text) - return clean_signature, self_parameter, last_positional_only - - -def _signature_fromstr(cls, obj, s, skip_bound_arg=True): - """Private helper to parse content of '__text_signature__' - and return a Signature based on it. - """ - # Lazy import ast because it's relatively heavy and - # it's not used for other than this function. - import ast - - Parameter = cls._parameter_cls - - clean_signature, self_parameter, last_positional_only = \ - _signature_strip_non_python_syntax(s) - - program = "def foo" + clean_signature + ": pass" - - try: - module = ast.parse(program) - except SyntaxError: - module = None - - if not isinstance(module, ast.Module): - raise ValueError("{!r} builtin has invalid signature".format(obj)) - - f = module.body[0] - - parameters = [] - empty = Parameter.empty - invalid = object() - - module = None - module_dict = {} - module_name = getattr(obj, '__module__', None) - if module_name: - module = sys.modules.get(module_name, None) - if module: - module_dict = module.__dict__ - sys_module_dict = sys.modules.copy() - - def parse_name(node): - assert isinstance(node, ast.arg) - if node.annotation is not None: - raise ValueError("Annotations are not currently supported") - return node.arg - - def wrap_value(s): - try: - value = eval(s, module_dict) - except NameError: - try: - value = eval(s, sys_module_dict) - except NameError: - raise RuntimeError() - - if isinstance(value, (str, int, float, bytes, bool, type(None))): - return ast.Constant(value) - raise RuntimeError() - - class RewriteSymbolics(ast.NodeTransformer): - def visit_Attribute(self, node): - a = [] - n = node - while isinstance(n, ast.Attribute): - a.append(n.attr) - n = n.value - if not isinstance(n, ast.Name): - raise RuntimeError() - a.append(n.id) - value = ".".join(reversed(a)) - return wrap_value(value) - - def visit_Name(self, node): - if not isinstance(node.ctx, ast.Load): - raise ValueError() - return wrap_value(node.id) - - def p(name_node, default_node, default=empty): - name = parse_name(name_node) - if name is invalid: - return None - if default_node and default_node is not _empty: - try: - default_node = RewriteSymbolics().visit(default_node) - o = ast.literal_eval(default_node) - except ValueError: - o = invalid - if o is invalid: - return None - default = o if o is not invalid else default - parameters.append(Parameter(name, kind, default=default, annotation=empty)) - - # non-keyword-only parameters - args = reversed(f.args.args) - defaults = reversed(f.args.defaults) - iter = itertools.zip_longest(args, defaults, fillvalue=None) - if last_positional_only is not None: - kind = Parameter.POSITIONAL_ONLY - else: - kind = Parameter.POSITIONAL_OR_KEYWORD - for i, (name, default) in enumerate(reversed(list(iter))): - p(name, default) - if i == last_positional_only: - kind = Parameter.POSITIONAL_OR_KEYWORD - - # *args - if f.args.vararg: - kind = Parameter.VAR_POSITIONAL - p(f.args.vararg, empty) - - # keyword-only arguments - kind = Parameter.KEYWORD_ONLY - for name, default in zip(f.args.kwonlyargs, f.args.kw_defaults): - p(name, default) - - # **kwargs - if f.args.kwarg: - kind = Parameter.VAR_KEYWORD - p(f.args.kwarg, empty) - - if self_parameter is not None: - # Possibly strip the bound argument: - # - We *always* strip first bound argument if - # it is a module. - # - We don't strip first bound argument if - # skip_bound_arg is False. - assert parameters - _self = getattr(obj, '__self__', None) - self_isbound = _self is not None - self_ismodule = ismodule(_self) - if self_isbound and (self_ismodule or skip_bound_arg): - parameters.pop(0) - else: - # for builtins, self parameter is always positional-only! - p = parameters[0].replace(kind=Parameter.POSITIONAL_ONLY) - parameters[0] = p - - return cls(parameters, return_annotation=cls.empty) - - -def _signature_from_builtin(cls, func, skip_bound_arg=True): - """Private helper function to get signature for - builtin callables. - """ - - if not _signature_is_builtin(func): - raise TypeError("{!r} is not a Python builtin " - "function".format(func)) - - s = getattr(func, "__text_signature__", None) - if not s: - raise ValueError("no signature found for builtin {!r}".format(func)) - - return _signature_fromstr(cls, func, s, skip_bound_arg) - - -def _signature_from_function(cls, func, skip_bound_arg=True, - globals=None, locals=None, eval_str=False): - """Private helper: constructs Signature for the given python function.""" - - is_duck_function = False - if not isfunction(func): - if _signature_is_functionlike(func): - is_duck_function = True - else: - # If it's not a pure Python function, and not a duck type - # of pure function: - raise TypeError('{!r} is not a Python function'.format(func)) - - s = getattr(func, "__text_signature__", None) - if s: - return _signature_fromstr(cls, func, s, skip_bound_arg) - - Parameter = cls._parameter_cls - - # Parameter information. - func_code = func.__code__ - pos_count = func_code.co_argcount - arg_names = func_code.co_varnames - posonly_count = func_code.co_posonlyargcount - positional = arg_names[:pos_count] - keyword_only_count = func_code.co_kwonlyargcount - keyword_only = arg_names[pos_count:pos_count + keyword_only_count] - annotations = get_annotations(func, globals=globals, locals=locals, eval_str=eval_str) - defaults = func.__defaults__ - kwdefaults = func.__kwdefaults__ - - if defaults: - pos_default_count = len(defaults) - else: - pos_default_count = 0 - - parameters = [] - - non_default_count = pos_count - pos_default_count - posonly_left = posonly_count - - # Non-keyword-only parameters w/o defaults. - for name in positional[:non_default_count]: - kind = _POSITIONAL_ONLY if posonly_left else _POSITIONAL_OR_KEYWORD - annotation = annotations.get(name, _empty) - parameters.append(Parameter(name, annotation=annotation, - kind=kind)) - if posonly_left: - posonly_left -= 1 - - # ... w/ defaults. - for offset, name in enumerate(positional[non_default_count:]): - kind = _POSITIONAL_ONLY if posonly_left else _POSITIONAL_OR_KEYWORD - annotation = annotations.get(name, _empty) - parameters.append(Parameter(name, annotation=annotation, - kind=kind, - default=defaults[offset])) - if posonly_left: - posonly_left -= 1 - - # *args - if func_code.co_flags & CO_VARARGS: - name = arg_names[pos_count + keyword_only_count] - annotation = annotations.get(name, _empty) - parameters.append(Parameter(name, annotation=annotation, - kind=_VAR_POSITIONAL)) - - # Keyword-only parameters. - for name in keyword_only: - default = _empty - if kwdefaults is not None: - default = kwdefaults.get(name, _empty) - - annotation = annotations.get(name, _empty) - parameters.append(Parameter(name, annotation=annotation, - kind=_KEYWORD_ONLY, - default=default)) - # **kwargs - if func_code.co_flags & CO_VARKEYWORDS: - index = pos_count + keyword_only_count - if func_code.co_flags & CO_VARARGS: - index += 1 - - name = arg_names[index] - annotation = annotations.get(name, _empty) - parameters.append(Parameter(name, annotation=annotation, - kind=_VAR_KEYWORD)) - - # Is 'func' is a pure Python function - don't validate the - # parameters list (for correct order and defaults), it should be OK. - return cls(parameters, - return_annotation=annotations.get('return', _empty), - __validate_parameters__=is_duck_function) - - -def _signature_from_callable(obj, *, - follow_wrapper_chains=True, - skip_bound_arg=True, - globals=None, - locals=None, - eval_str=False, - sigcls): - - """Private helper function to get signature for arbitrary - callable objects. - """ - - _get_signature_of = functools.partial(_signature_from_callable, - follow_wrapper_chains=follow_wrapper_chains, - skip_bound_arg=skip_bound_arg, - globals=globals, - locals=locals, - sigcls=sigcls, - eval_str=eval_str) - - if not callable(obj): - raise TypeError('{!r} is not a callable object'.format(obj)) - - if isinstance(obj, types.MethodType): - # In this case we skip the first parameter of the underlying - # function (usually `self` or `cls`). - sig = _get_signature_of(obj.__func__) - - if skip_bound_arg: - return _signature_bound_method(sig) - else: - return sig - - # Was this function wrapped by a decorator? - if follow_wrapper_chains: - obj = unwrap(obj, stop=(lambda f: hasattr(f, "__signature__"))) - if isinstance(obj, types.MethodType): - # If the unwrapped object is a *method*, we might want to - # skip its first parameter (self). - # See test_signature_wrapped_bound_method for details. - return _get_signature_of(obj) - - try: - sig = obj.__signature__ - except AttributeError: - pass - else: - if sig is not None: - if not isinstance(sig, Signature): - raise TypeError( - 'unexpected object {!r} in __signature__ ' - 'attribute'.format(sig)) - return sig - - try: - partialmethod = obj._partialmethod - except AttributeError: - pass - else: - if isinstance(partialmethod, functools.partialmethod): - # Unbound partialmethod (see functools.partialmethod) - # This means, that we need to calculate the signature - # as if it's a regular partial object, but taking into - # account that the first positional argument - # (usually `self`, or `cls`) will not be passed - # automatically (as for boundmethods) - - wrapped_sig = _get_signature_of(partialmethod.func) - - sig = _signature_get_partial(wrapped_sig, partialmethod, (None,)) - first_wrapped_param = tuple(wrapped_sig.parameters.values())[0] - if first_wrapped_param.kind is Parameter.VAR_POSITIONAL: - # First argument of the wrapped callable is `*args`, as in - # `partialmethod(lambda *args)`. - return sig - else: - sig_params = tuple(sig.parameters.values()) - assert (not sig_params or - first_wrapped_param is not sig_params[0]) - new_params = (first_wrapped_param,) + sig_params - return sig.replace(parameters=new_params) - - if isfunction(obj) or _signature_is_functionlike(obj): - # If it's a pure Python function, or an object that is duck type - # of a Python function (Cython functions, for instance), then: - return _signature_from_function(sigcls, obj, - skip_bound_arg=skip_bound_arg, - globals=globals, locals=locals, eval_str=eval_str) - - if _signature_is_builtin(obj): - return _signature_from_builtin(sigcls, obj, - skip_bound_arg=skip_bound_arg) - - if isinstance(obj, functools.partial): - wrapped_sig = _get_signature_of(obj.func) - return _signature_get_partial(wrapped_sig, obj) - - sig = None - if isinstance(obj, type): - # obj is a class or a metaclass - - # First, let's see if it has an overloaded __call__ defined - # in its metaclass - call = _signature_get_user_defined_method(type(obj), '__call__') - if call is not None: - sig = _get_signature_of(call) - else: - factory_method = None - new = _signature_get_user_defined_method(obj, '__new__') - init = _signature_get_user_defined_method(obj, '__init__') - # Now we check if the 'obj' class has an own '__new__' method - if '__new__' in obj.__dict__: - factory_method = new - # or an own '__init__' method - elif '__init__' in obj.__dict__: - factory_method = init - # If not, we take inherited '__new__' or '__init__', if present - elif new is not None: - factory_method = new - elif init is not None: - factory_method = init - - if factory_method is not None: - sig = _get_signature_of(factory_method) - - if sig is None: - # At this point we know, that `obj` is a class, with no user- - # defined '__init__', '__new__', or class-level '__call__' - - for base in obj.__mro__[:-1]: - # Since '__text_signature__' is implemented as a - # descriptor that extracts text signature from the - # class docstring, if 'obj' is derived from a builtin - # class, its own '__text_signature__' may be 'None'. - # Therefore, we go through the MRO (except the last - # class in there, which is 'object') to find the first - # class with non-empty text signature. - try: - text_sig = base.__text_signature__ - except AttributeError: - pass - else: - if text_sig: - # If 'base' class has a __text_signature__ attribute: - # return a signature based on it - return _signature_fromstr(sigcls, base, text_sig) - - # No '__text_signature__' was found for the 'obj' class. - # Last option is to check if its '__init__' is - # object.__init__ or type.__init__. - if type not in obj.__mro__: - # We have a class (not metaclass), but no user-defined - # __init__ or __new__ for it - if (obj.__init__ is object.__init__ and - obj.__new__ is object.__new__): - # Return a signature of 'object' builtin. - return sigcls.from_callable(object) - else: - raise ValueError( - 'no signature found for builtin type {!r}'.format(obj)) - - elif not isinstance(obj, _NonUserDefinedCallables): - # An object with __call__ - # We also check that the 'obj' is not an instance of - # _WrapperDescriptor or _MethodWrapper to avoid - # infinite recursion (and even potential segfault) - call = _signature_get_user_defined_method(type(obj), '__call__') - if call is not None: - try: - sig = _get_signature_of(call) - except ValueError as ex: - msg = 'no signature found for {!r}'.format(obj) - raise ValueError(msg) from ex - - if sig is not None: - # For classes and objects we skip the first parameter of their - # __call__, __new__, or __init__ methods - if skip_bound_arg: - return _signature_bound_method(sig) - else: - return sig - - if isinstance(obj, types.BuiltinFunctionType): - # Raise a nicer error message for builtins - msg = 'no signature found for builtin function {!r}'.format(obj) - raise ValueError(msg) - - raise ValueError('callable {!r} is not supported by signature'.format(obj)) - - -class _void: - """A private marker - used in Parameter & Signature.""" - - -class _empty: - """Marker object for Signature.empty and Parameter.empty.""" - - -class _ParameterKind(enum.IntEnum): - POSITIONAL_ONLY = 0 - POSITIONAL_OR_KEYWORD = 1 - VAR_POSITIONAL = 2 - KEYWORD_ONLY = 3 - VAR_KEYWORD = 4 - - def __str__(self): - return self._name_ - - @property - def description(self): - return _PARAM_NAME_MAPPING[self] - -_POSITIONAL_ONLY = _ParameterKind.POSITIONAL_ONLY -_POSITIONAL_OR_KEYWORD = _ParameterKind.POSITIONAL_OR_KEYWORD -_VAR_POSITIONAL = _ParameterKind.VAR_POSITIONAL -_KEYWORD_ONLY = _ParameterKind.KEYWORD_ONLY -_VAR_KEYWORD = _ParameterKind.VAR_KEYWORD - -_PARAM_NAME_MAPPING = { - _POSITIONAL_ONLY: 'positional-only', - _POSITIONAL_OR_KEYWORD: 'positional or keyword', - _VAR_POSITIONAL: 'variadic positional', - _KEYWORD_ONLY: 'keyword-only', - _VAR_KEYWORD: 'variadic keyword' -} - - -class Parameter: - """Represents a parameter in a function signature. - - Has the following public attributes: - - * name : str - The name of the parameter as a string. - * default : object - The default value for the parameter if specified. If the - parameter has no default value, this attribute is set to - `Parameter.empty`. - * annotation - The annotation for the parameter if specified. If the - parameter has no annotation, this attribute is set to - `Parameter.empty`. - * kind : str - Describes how argument values are bound to the parameter. - Possible values: `Parameter.POSITIONAL_ONLY`, - `Parameter.POSITIONAL_OR_KEYWORD`, `Parameter.VAR_POSITIONAL`, - `Parameter.KEYWORD_ONLY`, `Parameter.VAR_KEYWORD`. - """ - - __slots__ = ('_name', '_kind', '_default', '_annotation') - - POSITIONAL_ONLY = _POSITIONAL_ONLY - POSITIONAL_OR_KEYWORD = _POSITIONAL_OR_KEYWORD - VAR_POSITIONAL = _VAR_POSITIONAL - KEYWORD_ONLY = _KEYWORD_ONLY - VAR_KEYWORD = _VAR_KEYWORD - - empty = _empty - - def __init__(self, name, kind, *, default=_empty, annotation=_empty): - try: - self._kind = _ParameterKind(kind) - except ValueError: - raise ValueError(f'value {kind!r} is not a valid Parameter.kind') - if default is not _empty: - if self._kind in (_VAR_POSITIONAL, _VAR_KEYWORD): - msg = '{} parameters cannot have default values' - msg = msg.format(self._kind.description) - raise ValueError(msg) - self._default = default - self._annotation = annotation - - if name is _empty: - raise ValueError('name is a required attribute for Parameter') - - if not isinstance(name, str): - msg = 'name must be a str, not a {}'.format(type(name).__name__) - raise TypeError(msg) - - if name[0] == '.' and name[1:].isdigit(): - # These are implicit arguments generated by comprehensions. In - # order to provide a friendlier interface to users, we recast - # their name as "implicitN" and treat them as positional-only. - # See issue 19611. - if self._kind != _POSITIONAL_OR_KEYWORD: - msg = ( - 'implicit arguments must be passed as ' - 'positional or keyword arguments, not {}' - ) - msg = msg.format(self._kind.description) - raise ValueError(msg) - self._kind = _POSITIONAL_ONLY - name = 'implicit{}'.format(name[1:]) - - if not name.isidentifier(): - raise ValueError('{!r} is not a valid parameter name'.format(name)) - - self._name = name - - def __reduce__(self): - return (type(self), - (self._name, self._kind), - {'_default': self._default, - '_annotation': self._annotation}) - - def __setstate__(self, state): - self._default = state['_default'] - self._annotation = state['_annotation'] - - @property - def name(self): - return self._name - - @property - def default(self): - return self._default - - @property - def annotation(self): - return self._annotation - - @property - def kind(self): - return self._kind - - def replace(self, *, name=_void, kind=_void, - annotation=_void, default=_void): - """Creates a customized copy of the Parameter.""" - - if name is _void: - name = self._name - - if kind is _void: - kind = self._kind - - if annotation is _void: - annotation = self._annotation - - if default is _void: - default = self._default - - return type(self)(name, kind, default=default, annotation=annotation) - - def __str__(self): - kind = self.kind - formatted = self._name - - # Add annotation and default value - if self._annotation is not _empty: - formatted = '{}: {}'.format(formatted, - formatannotation(self._annotation)) - - if self._default is not _empty: - if self._annotation is not _empty: - formatted = '{} = {}'.format(formatted, repr(self._default)) - else: - formatted = '{}={}'.format(formatted, repr(self._default)) - - if kind == _VAR_POSITIONAL: - formatted = '*' + formatted - elif kind == _VAR_KEYWORD: - formatted = '**' + formatted - - return formatted - - def __repr__(self): - return '<{} "{}">'.format(self.__class__.__name__, self) - - def __hash__(self): - return hash((self.name, self.kind, self.annotation, self.default)) - - def __eq__(self, other): - if self is other: - return True - if not isinstance(other, Parameter): - return NotImplemented - return (self._name == other._name and - self._kind == other._kind and - self._default == other._default and - self._annotation == other._annotation) - - -class BoundArguments: - """Result of `Signature.bind` call. Holds the mapping of arguments - to the function's parameters. - - Has the following public attributes: - - * arguments : dict - An ordered mutable mapping of parameters' names to arguments' values. - Does not contain arguments' default values. - * signature : Signature - The Signature object that created this instance. - * args : tuple - Tuple of positional arguments values. - * kwargs : dict - Dict of keyword arguments values. - """ - - __slots__ = ('arguments', '_signature', '__weakref__') - - def __init__(self, signature, arguments): - self.arguments = arguments - self._signature = signature - - @property - def signature(self): - return self._signature - - @property - def args(self): - args = [] - for param_name, param in self._signature.parameters.items(): - if param.kind in (_VAR_KEYWORD, _KEYWORD_ONLY): - break - - try: - arg = self.arguments[param_name] - except KeyError: - # We're done here. Other arguments - # will be mapped in 'BoundArguments.kwargs' - break - else: - if param.kind == _VAR_POSITIONAL: - # *args - args.extend(arg) - else: - # plain argument - args.append(arg) - - return tuple(args) - - @property - def kwargs(self): - kwargs = {} - kwargs_started = False - for param_name, param in self._signature.parameters.items(): - if not kwargs_started: - if param.kind in (_VAR_KEYWORD, _KEYWORD_ONLY): - kwargs_started = True - else: - if param_name not in self.arguments: - kwargs_started = True - continue - - if not kwargs_started: - continue - - try: - arg = self.arguments[param_name] - except KeyError: - pass - else: - if param.kind == _VAR_KEYWORD: - # **kwargs - kwargs.update(arg) - else: - # plain keyword argument - kwargs[param_name] = arg - - return kwargs - - def apply_defaults(self): - """Set default values for missing arguments. - - For variable-positional arguments (*args) the default is an - empty tuple. - - For variable-keyword arguments (**kwargs) the default is an - empty dict. - """ - arguments = self.arguments - new_arguments = [] - for name, param in self._signature.parameters.items(): - try: - new_arguments.append((name, arguments[name])) - except KeyError: - if param.default is not _empty: - val = param.default - elif param.kind is _VAR_POSITIONAL: - val = () - elif param.kind is _VAR_KEYWORD: - val = {} - else: - # This BoundArguments was likely produced by - # Signature.bind_partial(). - continue - new_arguments.append((name, val)) - self.arguments = dict(new_arguments) - - def __eq__(self, other): - if self is other: - return True - if not isinstance(other, BoundArguments): - return NotImplemented - return (self.signature == other.signature and - self.arguments == other.arguments) - - def __setstate__(self, state): - self._signature = state['_signature'] - self.arguments = state['arguments'] - - def __getstate__(self): - return {'_signature': self._signature, 'arguments': self.arguments} - - def __repr__(self): - args = [] - for arg, value in self.arguments.items(): - args.append('{}={!r}'.format(arg, value)) - return '<{} ({})>'.format(self.__class__.__name__, ', '.join(args)) - - -class Signature: - """A Signature object represents the overall signature of a function. - It stores a Parameter object for each parameter accepted by the - function, as well as information specific to the function itself. - - A Signature object has the following public attributes and methods: - - * parameters : OrderedDict - An ordered mapping of parameters' names to the corresponding - Parameter objects (keyword-only arguments are in the same order - as listed in `code.co_varnames`). - * return_annotation : object - The annotation for the return type of the function if specified. - If the function has no annotation for its return type, this - attribute is set to `Signature.empty`. - * bind(*args, **kwargs) -> BoundArguments - Creates a mapping from positional and keyword arguments to - parameters. - * bind_partial(*args, **kwargs) -> BoundArguments - Creates a partial mapping from positional and keyword arguments - to parameters (simulating 'functools.partial' behavior.) - """ - - __slots__ = ('_return_annotation', '_parameters') - - _parameter_cls = Parameter - _bound_arguments_cls = BoundArguments - - empty = _empty - - def __init__(self, parameters=None, *, return_annotation=_empty, - __validate_parameters__=True): - """Constructs Signature from the given list of Parameter - objects and 'return_annotation'. All arguments are optional. - """ - - if parameters is None: - params = OrderedDict() - else: - if __validate_parameters__: - params = OrderedDict() - top_kind = _POSITIONAL_ONLY - kind_defaults = False - - for param in parameters: - kind = param.kind - name = param.name - - if kind < top_kind: - msg = ( - 'wrong parameter order: {} parameter before {} ' - 'parameter' - ) - msg = msg.format(top_kind.description, - kind.description) - raise ValueError(msg) - elif kind > top_kind: - kind_defaults = False - top_kind = kind - - if kind in (_POSITIONAL_ONLY, _POSITIONAL_OR_KEYWORD): - if param.default is _empty: - if kind_defaults: - # No default for this parameter, but the - # previous parameter of the same kind had - # a default - msg = 'non-default argument follows default ' \ - 'argument' - raise ValueError(msg) - else: - # There is a default for this parameter. - kind_defaults = True - - if name in params: - msg = 'duplicate parameter name: {!r}'.format(name) - raise ValueError(msg) - - params[name] = param - else: - params = OrderedDict((param.name, param) for param in parameters) - - self._parameters = types.MappingProxyType(params) - self._return_annotation = return_annotation - - @classmethod - def from_function(cls, func): - """Constructs Signature for the given python function. - - Deprecated since Python 3.5, use `Signature.from_callable()`. - """ - - warnings.warn("inspect.Signature.from_function() is deprecated since " - "Python 3.5, use Signature.from_callable()", - DeprecationWarning, stacklevel=2) - return _signature_from_function(cls, func) - - @classmethod - def from_builtin(cls, func): - """Constructs Signature for the given builtin function. - - Deprecated since Python 3.5, use `Signature.from_callable()`. - """ - - warnings.warn("inspect.Signature.from_builtin() is deprecated since " - "Python 3.5, use Signature.from_callable()", - DeprecationWarning, stacklevel=2) - return _signature_from_builtin(cls, func) - - @classmethod - def from_callable(cls, obj, *, - follow_wrapped=True, globals=None, locals=None, eval_str=False): - """Constructs Signature for the given callable object.""" - return _signature_from_callable(obj, sigcls=cls, - follow_wrapper_chains=follow_wrapped, - globals=globals, locals=locals, eval_str=eval_str) - - @property - def parameters(self): - return self._parameters - - @property - def return_annotation(self): - return self._return_annotation - - def replace(self, *, parameters=_void, return_annotation=_void): - """Creates a customized copy of the Signature. - Pass 'parameters' and/or 'return_annotation' arguments - to override them in the new copy. - """ - - if parameters is _void: - parameters = self.parameters.values() - - if return_annotation is _void: - return_annotation = self._return_annotation - - return type(self)(parameters, - return_annotation=return_annotation) - - def _hash_basis(self): - params = tuple(param for param in self.parameters.values() - if param.kind != _KEYWORD_ONLY) - - kwo_params = {param.name: param for param in self.parameters.values() - if param.kind == _KEYWORD_ONLY} - - return params, kwo_params, self.return_annotation - - def __hash__(self): - params, kwo_params, return_annotation = self._hash_basis() - kwo_params = frozenset(kwo_params.values()) - return hash((params, kwo_params, return_annotation)) - - def __eq__(self, other): - if self is other: - return True - if not isinstance(other, Signature): - return NotImplemented - return self._hash_basis() == other._hash_basis() - - def _bind(self, args, kwargs, *, partial=False): - """Private method. Don't use directly.""" - - arguments = {} - - parameters = iter(self.parameters.values()) - parameters_ex = () - arg_vals = iter(args) - - while True: - # Let's iterate through the positional arguments and corresponding - # parameters - try: - arg_val = next(arg_vals) - except StopIteration: - # No more positional arguments - try: - param = next(parameters) - except StopIteration: - # No more parameters. That's it. Just need to check that - # we have no `kwargs` after this while loop - break - else: - if param.kind == _VAR_POSITIONAL: - # That's OK, just empty *args. Let's start parsing - # kwargs - break - elif param.name in kwargs: - if param.kind == _POSITIONAL_ONLY: - msg = '{arg!r} parameter is positional only, ' \ - 'but was passed as a keyword' - msg = msg.format(arg=param.name) - raise TypeError(msg) from None - parameters_ex = (param,) - break - elif (param.kind == _VAR_KEYWORD or - param.default is not _empty): - # That's fine too - we have a default value for this - # parameter. So, lets start parsing `kwargs`, starting - # with the current parameter - parameters_ex = (param,) - break - else: - # No default, not VAR_KEYWORD, not VAR_POSITIONAL, - # not in `kwargs` - if partial: - parameters_ex = (param,) - break - else: - msg = 'missing a required argument: {arg!r}' - msg = msg.format(arg=param.name) - raise TypeError(msg) from None - else: - # We have a positional argument to process - try: - param = next(parameters) - except StopIteration: - raise TypeError('too many positional arguments') from None - else: - if param.kind in (_VAR_KEYWORD, _KEYWORD_ONLY): - # Looks like we have no parameter for this positional - # argument - raise TypeError( - 'too many positional arguments') from None - - if param.kind == _VAR_POSITIONAL: - # We have an '*args'-like argument, let's fill it with - # all positional arguments we have left and move on to - # the next phase - values = [arg_val] - values.extend(arg_vals) - arguments[param.name] = tuple(values) - break - - if param.name in kwargs and param.kind != _POSITIONAL_ONLY: - raise TypeError( - 'multiple values for argument {arg!r}'.format( - arg=param.name)) from None - - arguments[param.name] = arg_val - - # Now, we iterate through the remaining parameters to process - # keyword arguments - kwargs_param = None - for param in itertools.chain(parameters_ex, parameters): - if param.kind == _VAR_KEYWORD: - # Memorize that we have a '**kwargs'-like parameter - kwargs_param = param - continue - - if param.kind == _VAR_POSITIONAL: - # Named arguments don't refer to '*args'-like parameters. - # We only arrive here if the positional arguments ended - # before reaching the last parameter before *args. - continue - - param_name = param.name - try: - arg_val = kwargs.pop(param_name) - except KeyError: - # We have no value for this parameter. It's fine though, - # if it has a default value, or it is an '*args'-like - # parameter, left alone by the processing of positional - # arguments. - if (not partial and param.kind != _VAR_POSITIONAL and - param.default is _empty): - raise TypeError('missing a required argument: {arg!r}'. \ - format(arg=param_name)) from None - - else: - if param.kind == _POSITIONAL_ONLY: - # This should never happen in case of a properly built - # Signature object (but let's have this check here - # to ensure correct behaviour just in case) - raise TypeError('{arg!r} parameter is positional only, ' - 'but was passed as a keyword'. \ - format(arg=param.name)) - - arguments[param_name] = arg_val - - if kwargs: - if kwargs_param is not None: - # Process our '**kwargs'-like parameter - arguments[kwargs_param.name] = kwargs - else: - raise TypeError( - 'got an unexpected keyword argument {arg!r}'.format( - arg=next(iter(kwargs)))) - - return self._bound_arguments_cls(self, arguments) - - def bind(self, /, *args, **kwargs): - """Get a BoundArguments object, that maps the passed `args` - and `kwargs` to the function's signature. Raises `TypeError` - if the passed arguments can not be bound. - """ - return self._bind(args, kwargs) - - def bind_partial(self, /, *args, **kwargs): - """Get a BoundArguments object, that partially maps the - passed `args` and `kwargs` to the function's signature. - Raises `TypeError` if the passed arguments can not be bound. - """ - return self._bind(args, kwargs, partial=True) - - def __reduce__(self): - return (type(self), - (tuple(self._parameters.values()),), - {'_return_annotation': self._return_annotation}) - - def __setstate__(self, state): - self._return_annotation = state['_return_annotation'] - - def __repr__(self): - return '<{} {}>'.format(self.__class__.__name__, self) - - def __str__(self): - result = [] - render_pos_only_separator = False - render_kw_only_separator = True - for param in self.parameters.values(): - formatted = str(param) - - kind = param.kind - - if kind == _POSITIONAL_ONLY: - render_pos_only_separator = True - elif render_pos_only_separator: - # It's not a positional-only parameter, and the flag - # is set to 'True' (there were pos-only params before.) - result.append('/') - render_pos_only_separator = False - - if kind == _VAR_POSITIONAL: - # OK, we have an '*args'-like parameter, so we won't need - # a '*' to separate keyword-only arguments - render_kw_only_separator = False - elif kind == _KEYWORD_ONLY and render_kw_only_separator: - # We have a keyword-only parameter to render and we haven't - # rendered an '*args'-like parameter before, so add a '*' - # separator to the parameters list ("foo(arg1, *, arg2)" case) - result.append('*') - # This condition should be only triggered once, so - # reset the flag - render_kw_only_separator = False - - result.append(formatted) - - if render_pos_only_separator: - # There were only positional-only parameters, hence the - # flag was not reset to 'False' - result.append('/') - - rendered = '({})'.format(', '.join(result)) - - if self.return_annotation is not _empty: - anno = formatannotation(self.return_annotation) - rendered += ' -> {}'.format(anno) - - return rendered - - -def signature(obj, *, follow_wrapped=True, globals=None, locals=None, eval_str=False): - """Get a signature object for the passed callable.""" - return Signature.from_callable(obj, follow_wrapped=follow_wrapped, - globals=globals, locals=locals, eval_str=eval_str) - - -def _main(): - """ Logic for inspecting an object given at command line """ - import argparse - import importlib - - parser = argparse.ArgumentParser() - parser.add_argument( - 'object', - help="The object to be analysed. " - "It supports the 'module:qualname' syntax") - parser.add_argument( - '-d', '--details', action='store_true', - help='Display info about the module rather than its source code') - - args = parser.parse_args() - - target = args.object - mod_name, has_attrs, attrs = target.partition(":") - try: - obj = module = importlib.import_module(mod_name) - except Exception as exc: - msg = "Failed to import {} ({}: {})".format(mod_name, - type(exc).__name__, - exc) - print(msg, file=sys.stderr) - sys.exit(2) - - if has_attrs: - parts = attrs.split(".") - obj = module - for part in parts: - obj = getattr(obj, part) - - if module.__name__ in sys.builtin_module_names: - print("Can't get info for builtin modules.", file=sys.stderr) - sys.exit(1) - - if args.details: - print('Target: {}'.format(target)) - print('Origin: {}'.format(getsourcefile(module))) - print('Cached: {}'.format(module.__cached__)) - if obj is module: - print('Loader: {}'.format(repr(module.__loader__))) - if hasattr(module, '__path__'): - print('Submodule search path: {}'.format(module.__path__)) - else: - try: - __, lineno = findsource(obj) - except Exception: - pass - else: - print('Line: {}'.format(lineno)) - - print('\n') - else: - print(getsource(obj)) - - -if __name__ == "__main__": - _main() diff --git a/tanjun/_internal/vendor/inspect.py.LICENSE b/tanjun/_internal/vendor/inspect.py.LICENSE deleted file mode 100644 index 02a5145f0..000000000 --- a/tanjun/_internal/vendor/inspect.py.LICENSE +++ /dev/null @@ -1,279 +0,0 @@ -A. HISTORY OF THE SOFTWARE -========================== - -Python was created in the early 1990s by Guido van Rossum at Stichting -Mathematisch Centrum (CWI, see http://www.cwi.nl) in the Netherlands -as a successor of a language called ABC. Guido remains Python's -principal author, although it includes many contributions from others. - -In 1995, Guido continued his work on Python at the Corporation for -National Research Initiatives (CNRI, see http://www.cnri.reston.va.us) -in Reston, Virginia where he released several versions of the -software. - -In May 2000, Guido and the Python core development team moved to -BeOpen.com to form the BeOpen PythonLabs team. In October of the same -year, the PythonLabs team moved to Digital Creations, which became -Zope Corporation. In 2001, the Python Software Foundation (PSF, see -https://www.python.org/psf/) was formed, a non-profit organization -created specifically to own Python-related Intellectual Property. -Zope Corporation was a sponsoring member of the PSF. - -All Python releases are Open Source (see http://www.opensource.org for -the Open Source Definition). Historically, most, but not all, Python -releases have also been GPL-compatible; the table below summarizes -the various releases. - - Release Derived Year Owner GPL- - from compatible? (1) - - 0.9.0 thru 1.2 1991-1995 CWI yes - 1.3 thru 1.5.2 1.2 1995-1999 CNRI yes - 1.6 1.5.2 2000 CNRI no - 2.0 1.6 2000 BeOpen.com no - 1.6.1 1.6 2001 CNRI yes (2) - 2.1 2.0+1.6.1 2001 PSF no - 2.0.1 2.0+1.6.1 2001 PSF yes - 2.1.1 2.1+2.0.1 2001 PSF yes - 2.1.2 2.1.1 2002 PSF yes - 2.1.3 2.1.2 2002 PSF yes - 2.2 and above 2.1.1 2001-now PSF yes - -Footnotes: - -(1) GPL-compatible doesn't mean that we're distributing Python under - the GPL. All Python licenses, unlike the GPL, let you distribute - a modified version without making your changes open source. The - GPL-compatible licenses make it possible to combine Python with - other software that is released under the GPL; the others don't. - -(2) According to Richard Stallman, 1.6.1 is not GPL-compatible, - because its license has a choice of law clause. According to - CNRI, however, Stallman's lawyer has told CNRI's lawyer that 1.6.1 - is "not incompatible" with the GPL. - -Thanks to the many outside volunteers who have worked under Guido's -direction to make these releases possible. - - -B. TERMS AND CONDITIONS FOR ACCESSING OR OTHERWISE USING PYTHON -=============================================================== - -Python software and documentation are licensed under the -Python Software Foundation License Version 2. - -Starting with Python 3.8.6, examples, recipes, and other code in -the documentation are dual licensed under the PSF License Version 2 -and the Zero-Clause BSD license. - -Some software incorporated into Python is under different licenses. -The licenses are listed with code falling under that license. - - -PYTHON SOFTWARE FOUNDATION LICENSE VERSION 2 --------------------------------------------- - -1. This LICENSE AGREEMENT is between the Python Software Foundation -("PSF"), and the Individual or Organization ("Licensee") accessing and -otherwise using this software ("Python") in source or binary form and -its associated documentation. - -2. Subject to the terms and conditions of this License Agreement, PSF hereby -grants Licensee a nonexclusive, royalty-free, world-wide license to reproduce, -analyze, test, perform and/or display publicly, prepare derivative works, -distribute, and otherwise use Python alone or in any derivative version, -provided, however, that PSF's License Agreement and PSF's notice of copyright, -i.e., "Copyright (c) 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010, -2011, 2012, 2013, 2014, 2015, 2016, 2017, 2018, 2019, 2020, 2021, 2022 Python Software Foundation; -All Rights Reserved" are retained in Python alone or in any derivative version -prepared by Licensee. - -3. In the event Licensee prepares a derivative work that is based on -or incorporates Python or any part thereof, and wants to make -the derivative work available to others as provided herein, then -Licensee hereby agrees to include in any such work a brief summary of -the changes made to Python. - -4. PSF is making Python available to Licensee on an "AS IS" -basis. PSF MAKES NO REPRESENTATIONS OR WARRANTIES, EXPRESS OR -IMPLIED. BY WAY OF EXAMPLE, BUT NOT LIMITATION, PSF MAKES NO AND -DISCLAIMS ANY REPRESENTATION OR WARRANTY OF MERCHANTABILITY OR FITNESS -FOR ANY PARTICULAR PURPOSE OR THAT THE USE OF PYTHON WILL NOT -INFRINGE ANY THIRD PARTY RIGHTS. - -5. PSF SHALL NOT BE LIABLE TO LICENSEE OR ANY OTHER USERS OF PYTHON -FOR ANY INCIDENTAL, SPECIAL, OR CONSEQUENTIAL DAMAGES OR LOSS AS -A RESULT OF MODIFYING, DISTRIBUTING, OR OTHERWISE USING PYTHON, -OR ANY DERIVATIVE THEREOF, EVEN IF ADVISED OF THE POSSIBILITY THEREOF. - -6. This License Agreement will automatically terminate upon a material -breach of its terms and conditions. - -7. Nothing in this License Agreement shall be deemed to create any -relationship of agency, partnership, or joint venture between PSF and -Licensee. This License Agreement does not grant permission to use PSF -trademarks or trade name in a trademark sense to endorse or promote -products or services of Licensee, or any third party. - -8. By copying, installing or otherwise using Python, Licensee -agrees to be bound by the terms and conditions of this License -Agreement. - - -BEOPEN.COM LICENSE AGREEMENT FOR PYTHON 2.0 -------------------------------------------- - -BEOPEN PYTHON OPEN SOURCE LICENSE AGREEMENT VERSION 1 - -1. This LICENSE AGREEMENT is between BeOpen.com ("BeOpen"), having an -office at 160 Saratoga Avenue, Santa Clara, CA 95051, and the -Individual or Organization ("Licensee") accessing and otherwise using -this software in source or binary form and its associated -documentation ("the Software"). - -2. Subject to the terms and conditions of this BeOpen Python License -Agreement, BeOpen hereby grants Licensee a non-exclusive, -royalty-free, world-wide license to reproduce, analyze, test, perform -and/or display publicly, prepare derivative works, distribute, and -otherwise use the Software alone or in any derivative version, -provided, however, that the BeOpen Python License is retained in the -Software, alone or in any derivative version prepared by Licensee. - -3. BeOpen is making the Software available to Licensee on an "AS IS" -basis. BEOPEN MAKES NO REPRESENTATIONS OR WARRANTIES, EXPRESS OR -IMPLIED. BY WAY OF EXAMPLE, BUT NOT LIMITATION, BEOPEN MAKES NO AND -DISCLAIMS ANY REPRESENTATION OR WARRANTY OF MERCHANTABILITY OR FITNESS -FOR ANY PARTICULAR PURPOSE OR THAT THE USE OF THE SOFTWARE WILL NOT -INFRINGE ANY THIRD PARTY RIGHTS. - -4. BEOPEN SHALL NOT BE LIABLE TO LICENSEE OR ANY OTHER USERS OF THE -SOFTWARE FOR ANY INCIDENTAL, SPECIAL, OR CONSEQUENTIAL DAMAGES OR LOSS -AS A RESULT OF USING, MODIFYING OR DISTRIBUTING THE SOFTWARE, OR ANY -DERIVATIVE THEREOF, EVEN IF ADVISED OF THE POSSIBILITY THEREOF. - -5. This License Agreement will automatically terminate upon a material -breach of its terms and conditions. - -6. This License Agreement shall be governed by and interpreted in all -respects by the law of the State of California, excluding conflict of -law provisions. Nothing in this License Agreement shall be deemed to -create any relationship of agency, partnership, or joint venture -between BeOpen and Licensee. This License Agreement does not grant -permission to use BeOpen trademarks or trade names in a trademark -sense to endorse or promote products or services of Licensee, or any -third party. As an exception, the "BeOpen Python" logos available at -http://www.pythonlabs.com/logos.html may be used according to the -permissions granted on that web page. - -7. By copying, installing or otherwise using the software, Licensee -agrees to be bound by the terms and conditions of this License -Agreement. - - -CNRI LICENSE AGREEMENT FOR PYTHON 1.6.1 ---------------------------------------- - -1. This LICENSE AGREEMENT is between the Corporation for National -Research Initiatives, having an office at 1895 Preston White Drive, -Reston, VA 20191 ("CNRI"), and the Individual or Organization -("Licensee") accessing and otherwise using Python 1.6.1 software in -source or binary form and its associated documentation. - -2. Subject to the terms and conditions of this License Agreement, CNRI -hereby grants Licensee a nonexclusive, royalty-free, world-wide -license to reproduce, analyze, test, perform and/or display publicly, -prepare derivative works, distribute, and otherwise use Python 1.6.1 -alone or in any derivative version, provided, however, that CNRI's -License Agreement and CNRI's notice of copyright, i.e., "Copyright (c) -1995-2001 Corporation for National Research Initiatives; All Rights -Reserved" are retained in Python 1.6.1 alone or in any derivative -version prepared by Licensee. Alternately, in lieu of CNRI's License -Agreement, Licensee may substitute the following text (omitting the -quotes): "Python 1.6.1 is made available subject to the terms and -conditions in CNRI's License Agreement. This Agreement together with -Python 1.6.1 may be located on the internet using the following -unique, persistent identifier (known as a handle): 1895.22/1013. This -Agreement may also be obtained from a proxy server on the internet -using the following URL: http://hdl.handle.net/1895.22/1013". - -3. In the event Licensee prepares a derivative work that is based on -or incorporates Python 1.6.1 or any part thereof, and wants to make -the derivative work available to others as provided herein, then -Licensee hereby agrees to include in any such work a brief summary of -the changes made to Python 1.6.1. - -4. CNRI is making Python 1.6.1 available to Licensee on an "AS IS" -basis. CNRI MAKES NO REPRESENTATIONS OR WARRANTIES, EXPRESS OR -IMPLIED. BY WAY OF EXAMPLE, BUT NOT LIMITATION, CNRI MAKES NO AND -DISCLAIMS ANY REPRESENTATION OR WARRANTY OF MERCHANTABILITY OR FITNESS -FOR ANY PARTICULAR PURPOSE OR THAT THE USE OF PYTHON 1.6.1 WILL NOT -INFRINGE ANY THIRD PARTY RIGHTS. - -5. CNRI SHALL NOT BE LIABLE TO LICENSEE OR ANY OTHER USERS OF PYTHON -1.6.1 FOR ANY INCIDENTAL, SPECIAL, OR CONSEQUENTIAL DAMAGES OR LOSS AS -A RESULT OF MODIFYING, DISTRIBUTING, OR OTHERWISE USING PYTHON 1.6.1, -OR ANY DERIVATIVE THEREOF, EVEN IF ADVISED OF THE POSSIBILITY THEREOF. - -6. This License Agreement will automatically terminate upon a material -breach of its terms and conditions. - -7. This License Agreement shall be governed by the federal -intellectual property law of the United States, including without -limitation the federal copyright law, and, to the extent such -U.S. federal law does not apply, by the law of the Commonwealth of -Virginia, excluding Virginia's conflict of law provisions. -Notwithstanding the foregoing, with regard to derivative works based -on Python 1.6.1 that incorporate non-separable material that was -previously distributed under the GNU General Public License (GPL), the -law of the Commonwealth of Virginia shall govern this License -Agreement only as to issues arising under or with respect to -Paragraphs 4, 5, and 7 of this License Agreement. Nothing in this -License Agreement shall be deemed to create any relationship of -agency, partnership, or joint venture between CNRI and Licensee. This -License Agreement does not grant permission to use CNRI trademarks or -trade name in a trademark sense to endorse or promote products or -services of Licensee, or any third party. - -8. By clicking on the "ACCEPT" button where indicated, or by copying, -installing or otherwise using Python 1.6.1, Licensee agrees to be -bound by the terms and conditions of this License Agreement. - - ACCEPT - - -CWI LICENSE AGREEMENT FOR PYTHON 0.9.0 THROUGH 1.2 --------------------------------------------------- - -Copyright (c) 1991 - 1995, Stichting Mathematisch Centrum Amsterdam, -The Netherlands. All rights reserved. - -Permission to use, copy, modify, and distribute this software and its -documentation for any purpose and without fee is hereby granted, -provided that the above copyright notice appear in all copies and that -both that copyright notice and this permission notice appear in -supporting documentation, and that the name of Stichting Mathematisch -Centrum or CWI not be used in advertising or publicity pertaining to -distribution of the software without specific, written prior -permission. - -STICHTING MATHEMATISCH CENTRUM DISCLAIMS ALL WARRANTIES WITH REGARD TO -THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND -FITNESS, IN NO EVENT SHALL STICHTING MATHEMATISCH CENTRUM BE LIABLE -FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES -WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN -ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT -OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. - -ZERO-CLAUSE BSD LICENSE FOR CODE IN THE PYTHON DOCUMENTATION ----------------------------------------------------------------------- - -Permission to use, copy, modify, and/or distribute this software for any -purpose with or without fee is hereby granted. - -THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH -REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY -AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, -INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM -LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR -OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR -PERFORMANCE OF THIS SOFTWARE. diff --git a/tanjun/_internal/vendor/inspect.pyi b/tanjun/_internal/vendor/inspect.pyi deleted file mode 100644 index b9361bbc5..000000000 --- a/tanjun/_internal/vendor/inspect.pyi +++ /dev/null @@ -1,371 +0,0 @@ -# See ./inspect.pyi.LICENSE for license information. - -# Vendored from https://github.com/python/typeshed/blob/0e185f40877a614c5ddd87815707cf8153296872/stdlib/inspect.pyi -# with modifications which freeze it to 3.10's typeshed. -import enum -import sys -import types -from collections import OrderedDict -from collections.abc import Awaitable, Callable, Generator, Mapping, Sequence, Set as AbstractSet -from types import ( - AsyncGeneratorType, - BuiltinFunctionType, - BuiltinMethodType, - CodeType, - CoroutineType, - FrameType, - FunctionType, - GeneratorType, - GetSetDescriptorType, - LambdaType, - MethodType, - ModuleType, - TracebackType, -) - -if sys.version_info >= (3, 7): - from types import ClassMethodDescriptorType, WrapperDescriptorType, MemberDescriptorType, MethodDescriptorType - -from typing import Any, ClassVar, Coroutine, NamedTuple, Protocol, TypeVar, Union -from typing_extensions import Literal, ParamSpec, Self, TypeGuard - -_P = ParamSpec("_P") -_T_cont = TypeVar("_T_cont", contravariant=True) -_V_cont = TypeVar("_V_cont", contravariant=True) - -# -# Types and members -# -class EndOfBlock(Exception): ... - -class BlockFinder: - indent: int - islambda: bool - started: bool - passline: bool - indecorator: bool - decoratorhasargs: bool - last: int - def tokeneater(self, type: int, token: str, srowcol: tuple[int, int], erowcol: tuple[int, int], line: str) -> None: ... - -CO_OPTIMIZED: Literal[1] -CO_NEWLOCALS: Literal[2] -CO_VARARGS: Literal[4] -CO_VARKEYWORDS: Literal[8] -CO_NESTED: Literal[16] -CO_GENERATOR: Literal[32] -CO_NOFREE: Literal[64] -CO_COROUTINE: Literal[128] -CO_ITERABLE_COROUTINE: Literal[256] -CO_ASYNC_GENERATOR: Literal[512] -TPFLAGS_IS_ABSTRACT: Literal[1048576] - -modulesbyfile: dict[str, Any] - -def getmembers(object: object, predicate: Callable[[Any], bool] | None = ...) -> list[tuple[str, Any]]: ... -def getmodulename(path: str) -> str | None: ... -def ismodule(object: object) -> TypeGuard[ModuleType]: ... -def isclass(object: object) -> TypeGuard[type[Any]]: ... -def ismethod(object: object) -> TypeGuard[MethodType]: ... -def isfunction(object: object) -> TypeGuard[FunctionType]: ... - -if sys.version_info >= (3, 8): - def isgeneratorfunction(obj: object) -> bool: ... - def iscoroutinefunction(obj: object) -> bool: ... - -else: - def isgeneratorfunction(object: object) -> bool: ... - def iscoroutinefunction(object: object) -> bool: ... - -def isgenerator(object: object) -> TypeGuard[GeneratorType[Any, Any, Any]]: ... -def iscoroutine(object: object) -> TypeGuard[CoroutineType[Any, Any, Any]]: ... -def isawaitable(object: object) -> TypeGuard[Awaitable[Any]]: ... - -if sys.version_info >= (3, 8): - def isasyncgenfunction(obj: object) -> bool: ... - -else: - def isasyncgenfunction(object: object) -> bool: ... - -class _SupportsSet(Protocol[_T_cont, _V_cont]): - def __set__(self, __instance: _T_cont, __value: _V_cont) -> None: ... - -class _SupportsDelete(Protocol[_T_cont]): - def __delete__(self, __instance: _T_cont) -> None: ... - -def isasyncgen(object: object) -> TypeGuard[AsyncGeneratorType[Any, Any]]: ... -def istraceback(object: object) -> TypeGuard[TracebackType]: ... -def isframe(object: object) -> TypeGuard[FrameType]: ... -def iscode(object: object) -> TypeGuard[CodeType]: ... -def isbuiltin(object: object) -> TypeGuard[BuiltinFunctionType]: ... - -if sys.version_info >= (3, 7): - def isroutine( - object: object, - ) -> TypeGuard[ - FunctionType - | LambdaType - | MethodType - | BuiltinFunctionType - | BuiltinMethodType - | WrapperDescriptorType - | MethodDescriptorType - | ClassMethodDescriptorType - ]: ... - def ismethoddescriptor(object: object) -> TypeGuard[MethodDescriptorType]: ... - def ismemberdescriptor(object: object) -> TypeGuard[MemberDescriptorType]: ... - -else: - def isroutine( - object: object, - ) -> TypeGuard[FunctionType | LambdaType | MethodType | BuiltinFunctionType | BuiltinMethodType]: ... - def ismethoddescriptor(object: object) -> bool: ... - def ismemberdescriptor(object: object) -> bool: ... - -def isabstract(object: object) -> bool: ... -def isgetsetdescriptor(object: object) -> TypeGuard[GetSetDescriptorType]: ... -def isdatadescriptor(object: object) -> TypeGuard[_SupportsSet[Any, Any] | _SupportsDelete[Any]]: ... - -# -# Retrieving source code -# -_SourceObjectType = Union[ModuleType, type[Any], MethodType, FunctionType, TracebackType, FrameType, CodeType, Callable[..., Any]] - -def findsource(object: _SourceObjectType) -> tuple[list[str], int]: ... -def getabsfile(object: _SourceObjectType, _filename: str | None = ...) -> str: ... -def getblock(lines: Sequence[str]) -> Sequence[str]: ... -def getdoc(object: object) -> str | None: ... -def getcomments(object: object) -> str | None: ... -def getfile(object: _SourceObjectType) -> str: ... -def getmodule(object: object, _filename: str | None = ...) -> ModuleType | None: ... -def getsourcefile(object: _SourceObjectType) -> str | None: ... -def getsourcelines(object: _SourceObjectType) -> tuple[list[str], int]: ... -def getsource(object: _SourceObjectType) -> str: ... -def cleandoc(doc: str) -> str: ... -def indentsize(line: str) -> int: ... - -# -# Introspecting callables with the Signature object -# -def signature( - obj: Callable[..., Any], - *, - follow_wrapped: bool = ..., - globals: Mapping[str, Any] | None = ..., - locals: Mapping[str, Any] | None = ..., - eval_str: bool = ..., -) -> Signature: ... - -class _void: ... -class _empty: ... - -class Signature: - def __init__( - self, parameters: Sequence[Parameter] | None = ..., *, return_annotation: Any = ..., __validate_parameters__: bool = ... - ) -> None: ... - empty = _empty - @property - def parameters(self) -> types.MappingProxyType[str, Parameter]: ... - @property - def return_annotation(self) -> Any: ... - def bind(self, *args: Any, **kwargs: Any) -> BoundArguments: ... - def bind_partial(self, *args: Any, **kwargs: Any) -> BoundArguments: ... - def replace( - self, *, parameters: Sequence[Parameter] | type[_void] | None = ..., return_annotation: Any = ... - ) -> Self: ... - @classmethod - def from_callable( - cls, - obj: Callable[..., Any], - *, - follow_wrapped: bool = ..., - globals: Mapping[str, Any] | None = ..., - locals: Mapping[str, Any] | None = ..., - eval_str: bool = ..., - ) -> Self: ... - -def get_annotations( - obj: Callable[..., Any] | type[Any] | ModuleType, - *, - globals: Mapping[str, Any] | None = ..., - locals: Mapping[str, Any] | None = ..., - eval_str: bool = ..., -) -> dict[str, Any]: ... - -# The name is the same as the enum's name in CPython -class _ParameterKind(enum.IntEnum): - POSITIONAL_ONLY: int - POSITIONAL_OR_KEYWORD: int - VAR_POSITIONAL: int - KEYWORD_ONLY: int - VAR_KEYWORD: int - - if sys.version_info >= (3, 8): - @property - def description(self) -> str: ... - -class Parameter: - def __init__(self, name: str, kind: _ParameterKind, *, default: Any = ..., annotation: Any = ...) -> None: ... - empty = _empty - - POSITIONAL_ONLY: ClassVar[Literal[_ParameterKind.POSITIONAL_ONLY]] - POSITIONAL_OR_KEYWORD: ClassVar[Literal[_ParameterKind.POSITIONAL_OR_KEYWORD]] - VAR_POSITIONAL: ClassVar[Literal[_ParameterKind.VAR_POSITIONAL]] - KEYWORD_ONLY: ClassVar[Literal[_ParameterKind.KEYWORD_ONLY]] - VAR_KEYWORD: ClassVar[Literal[_ParameterKind.VAR_KEYWORD]] - @property - def name(self) -> str: ... - @property - def default(self) -> Any: ... - @property - def kind(self) -> _ParameterKind: ... - @property - def annotation(self) -> Any: ... - def replace( - self, - *, - name: str | type[_void] = ..., - kind: _ParameterKind | type[_void] = ..., - default: Any = ..., - annotation: Any = ..., - ) -> Self: ... - -class BoundArguments: - arguments: OrderedDict[str, Any] - args: tuple[Any, ...] - kwargs: dict[str, Any] - signature: Signature - def __init__(self, signature: Signature, arguments: OrderedDict[str, Any]) -> None: ... - def apply_defaults(self) -> None: ... - -# -# Classes and functions -# - -# TODO: The actual return type should be list[_ClassTreeItem] but mypy doesn't -# seem to be supporting this at the moment: -# _ClassTreeItem = list[_ClassTreeItem] | Tuple[type, Tuple[type, ...]] -def getclasstree(classes: list[type], unique: bool = ...) -> list[Any]: ... -def walktree(classes: list[type], children: dict[type[Any], list[type]], parent: type[Any] | None) -> list[Any]: ... - -class Arguments(NamedTuple): - args: list[str] - varargs: str | None - varkw: str | None - -def getargs(co: CodeType) -> Arguments: ... - -class FullArgSpec(NamedTuple): - args: list[str] - varargs: str | None - varkw: str | None - defaults: tuple[Any, ...] | None - kwonlyargs: list[str] - kwonlydefaults: dict[str, Any] | None - annotations: dict[str, Any] - -def getfullargspec(func: object) -> FullArgSpec: ... - -class ArgInfo(NamedTuple): - args: list[str] - varargs: str | None - keywords: str | None - locals: dict[str, Any] - -def getargvalues(frame: FrameType) -> ArgInfo: ... -def formatannotation(annotation: object, base_module: str | None = ...) -> str: ... -def formatannotationrelativeto(object: object) -> Callable[[object], str]: ... - -def formatargvalues( - args: list[str], - varargs: str | None, - varkw: str | None, - locals: dict[str, Any] | None, - formatarg: Callable[[str], str] | None = ..., - formatvarargs: Callable[[str], str] | None = ..., - formatvarkw: Callable[[str], str] | None = ..., - formatvalue: Callable[[Any], str] | None = ..., -) -> str: ... -def getmro(cls: type) -> tuple[type, ...]: ... -def getcallargs(__func: Callable[_P, Any], *args: _P.args, **kwds: _P.kwargs) -> dict[str, Any]: ... - -class ClosureVars(NamedTuple): - nonlocals: Mapping[str, Any] - globals: Mapping[str, Any] - builtins: Mapping[str, Any] - unbound: AbstractSet[str] - -def getclosurevars(func: Callable[..., Any]) -> ClosureVars: ... -def unwrap(func: Callable[..., Any], *, stop: Callable[[Any], Any] | None = ...) -> Any: ... - -# -# The interpreter stack -# - -class Traceback(NamedTuple): - filename: str - lineno: int - function: str - code_context: list[str] | None - index: int | None # type: ignore[assignment] - -class FrameInfo(NamedTuple): - frame: FrameType - filename: str - lineno: int - function: str - code_context: list[str] | None - index: int | None # type: ignore[assignment] - -def getframeinfo(frame: FrameType | TracebackType, context: int = ...) -> Traceback: ... -def getouterframes(frame: Any, context: int = ...) -> list[FrameInfo]: ... -def getinnerframes(tb: TracebackType, context: int = ...) -> list[FrameInfo]: ... -def getlineno(frame: FrameType) -> int: ... -def currentframe() -> FrameType | None: ... -def stack(context: int = ...) -> list[FrameInfo]: ... -def trace(context: int = ...) -> list[FrameInfo]: ... - -# -# Fetching attributes statically -# - -def getattr_static(obj: object, attr: str, default: Any | None = ...) -> Any: ... - -# -# Current State of Generators and Coroutines -# - -GEN_CREATED: Literal["GEN_CREATED"] -GEN_RUNNING: Literal["GEN_RUNNING"] -GEN_SUSPENDED: Literal["GEN_SUSPENDED"] -GEN_CLOSED: Literal["GEN_CLOSED"] - -def getgeneratorstate( - generator: Generator[Any, Any, Any] -) -> Literal["GEN_CREATED", "GEN_RUNNING", "GEN_SUSPENDED", "GEN_CLOSED"]: ... - -CORO_CREATED: Literal["CORO_CREATED"] -CORO_RUNNING: Literal["CORO_RUNNING"] -CORO_SUSPENDED: Literal["CORO_SUSPENDED"] -CORO_CLOSED: Literal["CORO_CLOSED"] - -def getcoroutinestate( - coroutine: Coroutine[Any, Any, Any] -) -> Literal["CORO_CREATED", "CORO_RUNNING", "CORO_SUSPENDED", "CORO_CLOSED"]: ... -def getgeneratorlocals(generator: Generator[Any, Any, Any]) -> dict[str, Any]: ... -def getcoroutinelocals(coroutine: Coroutine[Any, Any, Any]) -> dict[str, Any]: ... - -# Create private type alias to avoid conflict with symbol of same -# name created in Attribute class. -_Object = object - -class Attribute(NamedTuple): - name: str - kind: str - defining_class: type - object: _Object - -def classify_class_attrs(cls: type) -> list[Attribute]: ... - -if sys.version_info >= (3, 9): - class ClassFoundException(Exception): ... diff --git a/tanjun/_internal/vendor/inspect.pyi.LICENSE b/tanjun/_internal/vendor/inspect.pyi.LICENSE deleted file mode 100644 index 132644875..000000000 --- a/tanjun/_internal/vendor/inspect.pyi.LICENSE +++ /dev/null @@ -1,237 +0,0 @@ -The "typeshed" project is licensed under the terms of the Apache license, as -reproduced below. - -= = = = = - -Apache License - Version 2.0, January 2004 - http://www.apache.org/licenses/ - - TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION - - 1. Definitions. - - "License" shall mean the terms and conditions for use, reproduction, - and distribution as defined by Sections 1 through 9 of this document. - - "Licensor" shall mean the copyright owner or entity authorized by - the copyright owner that is granting the License. - - "Legal Entity" shall mean the union of the acting entity and all - other entities that control, are controlled by, or are under common - control with that entity. For the purposes of this definition, - "control" means (i) the power, direct or indirect, to cause the - direction or management of such entity, whether by contract or - otherwise, or (ii) ownership of fifty percent (50%) or more of the - outstanding shares, or (iii) beneficial ownership of such entity. - - "You" (or "Your") shall mean an individual or Legal Entity - exercising permissions granted by this License. - - "Source" form shall mean the preferred form for making modifications, - including but not limited to software source code, documentation - source, and configuration files. - - "Object" form shall mean any form resulting from mechanical - transformation or translation of a Source form, including but - not limited to compiled object code, generated documentation, - and conversions to other media types. - - "Work" shall mean the work of authorship, whether in Source or - Object form, made available under the License, as indicated by a - copyright notice that is included in or attached to the work - (an example is provided in the Appendix below). - - "Derivative Works" shall mean any work, whether in Source or Object - form, that is based on (or derived from) the Work and for which the - editorial revisions, annotations, elaborations, or other modifications - represent, as a whole, an original work of authorship. For the purposes - of this License, Derivative Works shall not include works that remain - separable from, or merely link (or bind by name) to the interfaces of, - the Work and Derivative Works thereof. - - "Contribution" shall mean any work of authorship, including - the original version of the Work and any modifications or additions - to that Work or Derivative Works thereof, that is intentionally - submitted to Licensor for inclusion in the Work by the copyright owner - or by an individual or Legal Entity authorized to submit on behalf of - the copyright owner. For the purposes of this definition, "submitted" - means any form of electronic, verbal, or written communication sent - to the Licensor or its representatives, including but not limited to - communication on electronic mailing lists, source code control systems, - and issue tracking systems that are managed by, or on behalf of, the - Licensor for the purpose of discussing and improving the Work, but - excluding communication that is conspicuously marked or otherwise - designated in writing by the copyright owner as "Not a Contribution." - - "Contributor" shall mean Licensor and any individual or Legal Entity - on behalf of whom a Contribution has been received by Licensor and - subsequently incorporated within the Work. - - 2. Grant of Copyright License. Subject to the terms and conditions of - this License, each Contributor hereby grants to You a perpetual, - worldwide, non-exclusive, no-charge, royalty-free, irrevocable - copyright license to reproduce, prepare Derivative Works of, - publicly display, publicly perform, sublicense, and distribute the - Work and such Derivative Works in Source or Object form. - - 3. Grant of Patent License. Subject to the terms and conditions of - this License, each Contributor hereby grants to You a perpetual, - worldwide, non-exclusive, no-charge, royalty-free, irrevocable - (except as stated in this section) patent license to make, have made, - use, offer to sell, sell, import, and otherwise transfer the Work, - where such license applies only to those patent claims licensable - by such Contributor that are necessarily infringed by their - Contribution(s) alone or by combination of their Contribution(s) - with the Work to which such Contribution(s) was submitted. If You - institute patent litigation against any entity (including a - cross-claim or counterclaim in a lawsuit) alleging that the Work - or a Contribution incorporated within the Work constitutes direct - or contributory patent infringement, then any patent licenses - granted to You under this License for that Work shall terminate - as of the date such litigation is filed. - - 4. Redistribution. You may reproduce and distribute copies of the - Work or Derivative Works thereof in any medium, with or without - modifications, and in Source or Object form, provided that You - meet the following conditions: - - (a) You must give any other recipients of the Work or - Derivative Works a copy of this License; and - - (b) You must cause any modified files to carry prominent notices - stating that You changed the files; and - - (c) You must retain, in the Source form of any Derivative Works - that You distribute, all copyright, patent, trademark, and - attribution notices from the Source form of the Work, - excluding those notices that do not pertain to any part of - the Derivative Works; and - - (d) If the Work includes a "NOTICE" text file as part of its - distribution, then any Derivative Works that You distribute must - include a readable copy of the attribution notices contained - within such NOTICE file, excluding those notices that do not - pertain to any part of the Derivative Works, in at least one - of the following places: within a NOTICE text file distributed - as part of the Derivative Works; within the Source form or - documentation, if provided along with the Derivative Works; or, - within a display generated by the Derivative Works, if and - wherever such third-party notices normally appear. The contents - of the NOTICE file are for informational purposes only and - do not modify the License. You may add Your own attribution - notices within Derivative Works that You distribute, alongside - or as an addendum to the NOTICE text from the Work, provided - that such additional attribution notices cannot be construed - as modifying the License. - - You may add Your own copyright statement to Your modifications and - may provide additional or different license terms and conditions - for use, reproduction, or distribution of Your modifications, or - for any such Derivative Works as a whole, provided Your use, - reproduction, and distribution of the Work otherwise complies with - the conditions stated in this License. - - 5. Submission of Contributions. Unless You explicitly state otherwise, - any Contribution intentionally submitted for inclusion in the Work - by You to the Licensor shall be under the terms and conditions of - this License, without any additional terms or conditions. - Notwithstanding the above, nothing herein shall supersede or modify - the terms of any separate license agreement you may have executed - with Licensor regarding such Contributions. - - 6. Trademarks. This License does not grant permission to use the trade - names, trademarks, service marks, or product names of the Licensor, - except as required for reasonable and customary use in describing the - origin of the Work and reproducing the content of the NOTICE file. - - 7. Disclaimer of Warranty. Unless required by applicable law or - agreed to in writing, Licensor provides the Work (and each - Contributor provides its Contributions) on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or - implied, including, without limitation, any warranties or conditions - of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A - PARTICULAR PURPOSE. You are solely responsible for determining the - appropriateness of using or redistributing the Work and assume any - risks associated with Your exercise of permissions under this License. - - 8. Limitation of Liability. In no event and under no legal theory, - whether in tort (including negligence), contract, or otherwise, - unless required by applicable law (such as deliberate and grossly - negligent acts) or agreed to in writing, shall any Contributor be - liable to You for damages, including any direct, indirect, special, - incidental, or consequential damages of any character arising as a - result of this License or out of the use or inability to use the - Work (including but not limited to damages for loss of goodwill, - work stoppage, computer failure or malfunction, or any and all - other commercial damages or losses), even if such Contributor - has been advised of the possibility of such damages. - - 9. Accepting Warranty or Additional Liability. While redistributing - the Work or Derivative Works thereof, You may choose to offer, - and charge a fee for, acceptance of support, warranty, indemnity, - or other liability obligations and/or rights consistent with this - License. However, in accepting such obligations, You may act only - on Your own behalf and on Your sole responsibility, not on behalf - of any other Contributor, and only if You agree to indemnify, - defend, and hold each Contributor harmless for any liability - incurred by, or claims asserted against, such Contributor by reason - of your accepting any such warranty or additional liability. - - END OF TERMS AND CONDITIONS - - APPENDIX: How to apply the Apache License to your work. - - To apply the Apache License to your work, attach the following - boilerplate notice, with the fields enclosed by brackets "{}" - replaced with your own identifying information. (Don't include - the brackets!) The text should be enclosed in the appropriate - comment syntax for the file format. We also recommend that a - file or class name and description of purpose be included on the - same "printed page" as the copyright notice for easier - identification within third-party archives. - - Copyright {yyyy} {name of copyright owner} - - Licensed under the Apache License, Version 2.0 (the "License"); - you may not use this file except in compliance with the License. - You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - - Unless required by applicable law or agreed to in writing, software - distributed under the License is distributed on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - See the License for the specific language governing permissions and - limitations under the License. - -= = = = = - -Parts of typeshed are licensed under different licenses (like the MIT -license), reproduced below. - -= = = = = - -The MIT License - -Copyright (c) 2015 Jukka Lehtosalo and contributors - -Permission is hereby granted, free of charge, to any person obtaining a -copy of this software and associated documentation files (the "Software"), -to deal in the Software without restriction, including without limitation -the rights to use, copy, modify, merge, publish, distribute, sublicense, -and/or sell copies of the Software, and to permit persons to whom the -Software is furnished to do so, subject to the following conditions: - -The above copyright notice and this permission notice shall be included in -all copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING -FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER -DEALINGS IN THE SOFTWARE. - -= = = = = diff --git a/tanjun/abc.py b/tanjun/abc.py index 61bc3183a..7a5f437f5 100644 --- a/tanjun/abc.py +++ b/tanjun/abc.py @@ -82,8 +82,7 @@ import asyncio import datetime import pathlib - - from typing_extensions import Self + from typing import Self from . import errors @@ -125,7 +124,7 @@ CommandCallbackSig = collections.Callable[..., _CoroT[None]] """Deprecated type hint used to represent any command callback.""" -MetaEventSig = collections.Callable[..., typing.Union[_CoroT[None], None]] +MetaEventSig = collections.Callable[..., _CoroT[None] | None] """Type hint of a client callback. The positional arguments this is guaranteed depend on the event name its being @@ -134,131 +133,108 @@ synchronous or asynchronous but must return [None][]. """ -# 3.9 and 3.10 just can't handle ending Concatenate with ... so we lie about this at runtime. -if typing.TYPE_CHECKING: - import typing_extensions - - _MaybeAwaitable = typing.Union[_CoroT[_T], _T] - - AutocompleteSig = collections.Callable[ - typing_extensions.Concatenate["AutocompleteContext", _AutocompleteValueT, ...], _CoroT[None] - ] - """Type hint of the signature an autocomplete callback should have. +_MaybeAwaitable = _CoroT[_T] | _T - This represents the signature - `async def (AutocompleteContext, int | str | float) -> None` - where dependency injection is supported. - """ +AutocompleteSig = collections.Callable[ + typing.Concatenate["AutocompleteContext", _AutocompleteValueT, ...], _CoroT[None] +] +"""Type hint of the signature an autocomplete callback should have. - CheckSig = collections.Callable[typing_extensions.Concatenate[_ContextT_contra, ...], _MaybeAwaitable[bool]] - """Type hint of a generic context check used with Tanjun commands. +This represents the signature +`async def (AutocompleteContext, int | str | float) -> None` +where dependency injection is supported. +""" - This may be registered with a command, client or component to add a rule - which decides whether it should execute for each context passed to it. +CheckSig = collections.Callable[typing.Concatenate[_ContextT_contra, ...], _MaybeAwaitable[bool]] +"""Type hint of a generic context check used with Tanjun commands. - This represents the signatures `def (Context, ...) -> bool | None` - and `async def (Context, ...) -> bool | None` where dependency - injection is supported. +This may be registered with a command, client or component to add a rule +which decides whether it should execute for each context passed to it. - Check callbacks may either return [False][] to indicate that the current - command(s) don't match the context (without stopping execution) or raise - [tanjun.FailedCheck][] to indicate that command execution should be halted - early and marked as not found. - """ +This represents the signatures `def (Context, ...) -> bool | None` +and `async def (Context, ...) -> bool | None` where dependency +injection is supported. - AnyCheckSig = CheckSig["Context"] - """Type hint of a check callback for any command type.""" +Check callbacks may either return [False][] to indicate that the current +command(s) don't match the context (without stopping execution) or raise +[tanjun.FailedCheck][] to indicate that command execution should be halted +early and marked as not found. +""" - MenuCallbackSig = collections.Callable[typing_extensions.Concatenate["MenuContext", _MenuValueT, ...], _CoroT[None]] - """Type hint of a context menu command callback. +AnyCheckSig = CheckSig["Context"] +"""Type hint of a check callback for any command type.""" - This represents the signature - `async def (MenuContext, hikari.Message, ...) -> None` or - `async def (MenuContext, hikari.InteractionMember, ...) -> None` - where dependency injection is supported. - """ +MenuCallbackSig = collections.Callable[typing.Concatenate["MenuContext", _MenuValueT, ...], _CoroT[None]] +"""Type hint of a context menu command callback. - _CommandCallbackSig = collections.Callable[typing_extensions.Concatenate[_ContextT_contra, ...], _CoroT[None]] +This represents the signature +`async def (MenuContext, hikari.Message, ...) -> None` or +`async def (MenuContext, hikari.InteractionMember, ...) -> None` +where dependency injection is supported. +""" - MessageCallbackSig = _CommandCallbackSig["MessageContext"] - """Type hint of a message command callback. +_CommandCallbackSig = collections.Callable[typing.Concatenate[_ContextT_contra, ...], _CoroT[None]] - This represents the signature `async def (MessageContext, ...) -> None` - where dependency injection is supported. - """ +MessageCallbackSig = _CommandCallbackSig["MessageContext"] +"""Type hint of a message command callback. - SlashCallbackSig = _CommandCallbackSig["SlashContext"] - """Type hint of a slash command callback. - - This represents the signature `async def (SlashContext, ...) -> None` - where dependency injection is supported. - """ +This represents the signature `async def (MessageContext, ...) -> None` +where dependency injection is supported. +""" - ErrorHookSig = collections.Callable[ - typing_extensions.Concatenate[_ContextT_contra, Exception, ...], _MaybeAwaitable[typing.Optional[bool]] - ] - """Type hint of the callback used as a unexpected command error hook. +SlashCallbackSig = _CommandCallbackSig["SlashContext"] +"""Type hint of a slash command callback. - This will be called whenever an unexpected [Exception][] is raised during the - execution stage of a command (ignoring [tanjun.ParserError][] and expected - [tanjun.TanjunError][] subclasses). +This represents the signature `async def (SlashContext, ...) -> None` +where dependency injection is supported. +""" - This represents the signatures `def (Context, Exception, ...) -> bool | None` - and `async def (Context, Exception, ...) -> bool | None` where - dependency injection is supported. +ErrorHookSig = collections.Callable[typing.Concatenate[_ContextT_contra, Exception, ...], _MaybeAwaitable[bool | None]] +"""Type hint of the callback used as a unexpected command error hook. - [True][] is returned to indicate that the exception should be suppressed and - [False][] is returned to indicate that the exception should be re-raised. - """ +This will be called whenever an unexpected [Exception][] is raised during the +execution stage of a command (ignoring [tanjun.ParserError][] and expected +[tanjun.TanjunError][] subclasses). - ParserHookSig = collections.Callable[ - typing_extensions.Concatenate[_ContextT_contra, "errors.ParserError", ...], - _MaybeAwaitable[typing.Optional[bool]], - ] - """Type hint of the callback used as a command parser error hook. +This represents the signatures `def (Context, Exception, ...) -> bool | None` +and `async def (Context, Exception, ...) -> bool | None` where +dependency injection is supported. - This will be called whenever an parser [ParserError][tanjun.errors.ParserError] - is raised during the execution stage of a command. +[True][] is returned to indicate that the exception should be suppressed and +[False][] is returned to indicate that the exception should be re-raised. +""" - This represents the signatures `def (Context, tanjun.ParserError, ...) -> None` - and `async def (Context, tanjun.ParserError, ...) -> None` where - dependency injection is supported. +ParserHookSig = collections.Callable[ + typing.Concatenate[_ContextT_contra, "errors.ParserError", ...], _MaybeAwaitable[bool | None] +] +"""Type hint of the callback used as a command parser error hook. - Parser errors are always suppressed (unlike general errors). - """ +This will be called whenever an parser [ParserError][tanjun.errors.ParserError] +is raised during the execution stage of a command. - HookSig = collections.Callable[typing_extensions.Concatenate[_ContextT_contra, ...], _MaybeAwaitable[None]] - """Type hint of the callback used as a general command hook. +This represents the signatures `def (Context, tanjun.ParserError, ...) -> None` +and `async def (Context, tanjun.ParserError, ...) -> None` where +dependency injection is supported. - This represents the signatures `def (Context, ...) -> None` and - `async def (Context, ...) -> None` where dependency injection is - supported. - """ +Parser errors are always suppressed (unlike general errors). +""" - _EventT = typing.TypeVar("_EventT", bound=hikari.Event) +HookSig = collections.Callable[typing.Concatenate[_ContextT_contra, ...], _MaybeAwaitable[None]] +"""Type hint of the callback used as a general command hook. - ListenerCallbackSig = collections.Callable[typing_extensions.Concatenate[_EventT, ...], _CoroT[None]] - """Type hint of a hikari event manager callback. +This represents the signatures `def (Context, ...) -> None` and +`async def (Context, ...) -> None` where dependency injection is +supported. +""" - This represents the signature `async def (hikari.Event, ...) -> None` where - dependency injection is supported. - """ +_EventT = typing.TypeVar("_EventT", bound=hikari.Event) -# 3.9 and 3.10 just can't handle ending Concatenate with ... so we lie about this at runtime. -else: - import types +ListenerCallbackSig = collections.Callable[typing.Concatenate[_EventT, ...], _CoroT[None]] +"""Type hint of a hikari event manager callback. - AutocompleteSig = types.GenericAlias(collections.Callable[..., typing.Any], (_AutocompleteValueT,)) - CheckSig = types.GenericAlias(collections.Callable[..., typing.Any], (_ContextT_contra,)) - AnyCheckSig = CheckSig["Context"] - MenuCallbackSig = types.GenericAlias(collections.Callable[..., typing.Any], (_MenuValueT,)) - MessageCallbackSig = collections.Callable[..., typing.Any] - SlashCallbackSig = collections.Callable[..., typing.Any] - ErrorHookSig = types.GenericAlias(collections.Callable[..., typing.Any], (_ContextT_contra,)) - ParserHookSig = types.GenericAlias(collections.Callable[..., typing.Any], (_ContextT_contra,)) - HookSig = types.GenericAlias(collections.Callable[..., typing.Any], (_ContextT_contra,)) - _EventT = typing.TypeVar("_EventT", bound=hikari.Event) - ListenerCallbackSig = types.GenericAlias(collections.Callable[..., typing.Any], (_EventT,)) +This represents the signature `async def (hikari.Event, ...) -> None` where +dependency injection is supported. +""" AutocompleteCallbackSig = AutocompleteSig[_AutocompleteValueT] @@ -304,7 +280,7 @@ def channel_id(self) -> hikari.Snowflake: @property @abc.abstractmethod - def cache(self) -> typing.Optional[hikari.api.Cache]: + def cache(self) -> hikari.api.Cache | None: """Hikari cache instance this context's command client was initialised with.""" @property @@ -314,7 +290,7 @@ def client(self) -> Client: @property @abc.abstractmethod - def component(self) -> typing.Optional[Component]: + def component(self) -> Component | None: """Object of the [Component][tanjun.abc.Component] this context is bound to. !!! note @@ -324,7 +300,7 @@ def component(self) -> typing.Optional[Component]: @property # TODO: can we somehow have this always be present on the command execution facing interface @abc.abstractmethod - def command(self) -> typing.Optional[ExecutableCommand[Self]]: + def command(self) -> ExecutableCommand[Self] | None: """Object of the command this context is bound to. !!! note @@ -339,12 +315,12 @@ def created_at(self) -> datetime.datetime: @property @abc.abstractmethod - def events(self) -> typing.Optional[hikari.api.EventManager]: + def events(self) -> hikari.api.EventManager | None: """Object of the event manager this context's client was initialised with.""" @property @abc.abstractmethod - def guild_id(self) -> typing.Optional[hikari.Snowflake]: + def guild_id(self) -> hikari.Snowflake | None: """ID of the guild this command was executed in. Will be [None][] for all DM command executions. @@ -365,7 +341,7 @@ def is_human(self) -> bool: @property @abc.abstractmethod - def member(self) -> typing.Optional[hikari.Member]: + def member(self) -> hikari.Member | None: """Guild member object of this command's author. Will be [None][] for DM command executions. @@ -373,7 +349,7 @@ def member(self) -> typing.Optional[hikari.Member]: @property @abc.abstractmethod - def server(self) -> typing.Optional[hikari.api.InteractionServer]: + def server(self) -> hikari.api.InteractionServer | None: """Object of the Hikari interaction server provided for this context's client.""" @property @@ -383,7 +359,7 @@ def rest(self) -> hikari.api.RESTClient: @property @abc.abstractmethod - def shard(self) -> typing.Optional[hikari.api.GatewayShard]: + def shard(self) -> hikari.api.GatewayShard | None: """Shard that triggered the context. !!! note @@ -393,12 +369,12 @@ def shard(self) -> typing.Optional[hikari.api.GatewayShard]: @property @abc.abstractmethod - def shards(self) -> typing.Optional[hikari.ShardAware]: + def shards(self) -> hikari.ShardAware | None: """Object of the Hikari shard manager this context's client was initialised with.""" @property @abc.abstractmethod - def voice(self) -> typing.Optional[hikari.api.VoiceComponent]: + def voice(self) -> hikari.api.VoiceComponent | None: """Object of the Hikari voice component this context's client was initialised with.""" @property @@ -407,7 +383,7 @@ def triggering_name(self) -> str: """Command name this execution was triggered with.""" @abc.abstractmethod - def set_component(self, component: typing.Optional[Component], /) -> Self: + def set_component(self, component: Component | None, /) -> Self: raise NotImplementedError @abc.abstractmethod @@ -444,7 +420,7 @@ async def fetch_channel(self) -> hikari.TextableChannel: """ @abc.abstractmethod - async def fetch_guild(self) -> typing.Optional[hikari.Guild]: + async def fetch_guild(self) -> hikari.Guild | None: """Fetch the guild the context was invoked in. !!! note @@ -475,7 +451,7 @@ async def fetch_guild(self) -> typing.Optional[hikari.Guild]: """ @abc.abstractmethod - def get_channel(self) -> typing.Optional[hikari.TextableGuildChannel]: + def get_channel(self) -> hikari.TextableGuildChannel | None: """Retrieve the channel the context was invoked in from the cache. !!! note @@ -492,7 +468,7 @@ def get_channel(self) -> typing.Optional[hikari.TextableGuildChannel]: """ @abc.abstractmethod - def get_guild(self) -> typing.Optional[hikari.Guild]: + def get_guild(self) -> hikari.Guild | None: """Fetch the guild that the context was invoked in. !!! note @@ -532,7 +508,7 @@ async def edit_initial_response( self, content: hikari.UndefinedOr[typing.Any] = hikari.UNDEFINED, *, - delete_after: typing.Union[datetime.timedelta, float, int, None] = None, + delete_after: datetime.timedelta | float | int | None = None, attachment: hikari.UndefinedNoneOr[hikari.Resourceish] = hikari.UNDEFINED, attachments: hikari.UndefinedNoneOr[collections.Sequence[hikari.Resourceish]] = hikari.UNDEFINED, component: hikari.UndefinedNoneOr[hikari.api.ComponentBuilder] = hikari.UNDEFINED, @@ -540,12 +516,8 @@ async def edit_initial_response( embed: hikari.UndefinedNoneOr[hikari.Embed] = hikari.UNDEFINED, embeds: hikari.UndefinedNoneOr[collections.Sequence[hikari.Embed]] = hikari.UNDEFINED, mentions_everyone: hikari.UndefinedOr[bool] = hikari.UNDEFINED, - user_mentions: typing.Union[ - hikari.SnowflakeishSequence[hikari.PartialUser], bool, hikari.UndefinedType - ] = hikari.UNDEFINED, - role_mentions: typing.Union[ - hikari.SnowflakeishSequence[hikari.PartialRole], bool, hikari.UndefinedType - ] = hikari.UNDEFINED, + user_mentions: hikari.SnowflakeishSequence[hikari.PartialUser] | bool | hikari.UndefinedType = hikari.UNDEFINED, + role_mentions: hikari.SnowflakeishSequence[hikari.PartialRole] | bool | hikari.UndefinedType = hikari.UNDEFINED, ) -> hikari.Message: """Edit the initial response for this context. @@ -644,7 +616,7 @@ async def edit_last_response( self, content: hikari.UndefinedOr[typing.Any] = hikari.UNDEFINED, *, - delete_after: typing.Union[datetime.timedelta, float, int, None] = None, + delete_after: datetime.timedelta | float | int | None = None, attachment: hikari.UndefinedNoneOr[hikari.Resourceish] = hikari.UNDEFINED, attachments: hikari.UndefinedNoneOr[collections.Sequence[hikari.Resourceish]] = hikari.UNDEFINED, component: hikari.UndefinedNoneOr[hikari.api.ComponentBuilder] = hikari.UNDEFINED, @@ -652,12 +624,8 @@ async def edit_last_response( embed: hikari.UndefinedNoneOr[hikari.Embed] = hikari.UNDEFINED, embeds: hikari.UndefinedNoneOr[collections.Sequence[hikari.Embed]] = hikari.UNDEFINED, mentions_everyone: hikari.UndefinedOr[bool] = hikari.UNDEFINED, - user_mentions: typing.Union[ - hikari.SnowflakeishSequence[hikari.PartialUser], bool, hikari.UndefinedType - ] = hikari.UNDEFINED, - role_mentions: typing.Union[ - hikari.SnowflakeishSequence[hikari.PartialRole], bool, hikari.UndefinedType - ] = hikari.UNDEFINED, + user_mentions: hikari.SnowflakeishSequence[hikari.PartialUser] | bool | hikari.UndefinedType = hikari.UNDEFINED, + role_mentions: hikari.SnowflakeishSequence[hikari.PartialRole] | bool | hikari.UndefinedType = hikari.UNDEFINED, ) -> hikari.Message: """Edit the last response for this context. @@ -778,7 +746,7 @@ async def respond( content: hikari.UndefinedOr[typing.Any] = hikari.UNDEFINED, *, ensure_result: typing.Literal[True], - delete_after: typing.Union[datetime.timedelta, float, int, None] = None, + delete_after: datetime.timedelta | float | int | None = None, attachment: hikari.UndefinedOr[hikari.Resourceish] = hikari.UNDEFINED, attachments: hikari.UndefinedOr[collections.Sequence[hikari.Resourceish]] = hikari.UNDEFINED, component: hikari.UndefinedOr[hikari.api.ComponentBuilder] = hikari.UNDEFINED, @@ -786,12 +754,8 @@ async def respond( embed: hikari.UndefinedOr[hikari.Embed] = hikari.UNDEFINED, embeds: hikari.UndefinedOr[collections.Sequence[hikari.Embed]] = hikari.UNDEFINED, mentions_everyone: hikari.UndefinedOr[bool] = hikari.UNDEFINED, - user_mentions: typing.Union[ - hikari.SnowflakeishSequence[hikari.PartialUser], bool, hikari.UndefinedType - ] = hikari.UNDEFINED, - role_mentions: typing.Union[ - hikari.SnowflakeishSequence[hikari.PartialRole], bool, hikari.UndefinedType - ] = hikari.UNDEFINED, + user_mentions: hikari.SnowflakeishSequence[hikari.PartialUser] | bool | hikari.UndefinedType = hikari.UNDEFINED, + role_mentions: hikari.SnowflakeishSequence[hikari.PartialRole] | bool | hikari.UndefinedType = hikari.UNDEFINED, ) -> hikari.Message: ... @typing.overload @@ -801,7 +765,7 @@ async def respond( content: hikari.UndefinedOr[typing.Any] = hikari.UNDEFINED, *, ensure_result: bool = False, - delete_after: typing.Union[datetime.timedelta, float, int, None] = None, + delete_after: datetime.timedelta | float | int | None = None, attachment: hikari.UndefinedOr[hikari.Resourceish] = hikari.UNDEFINED, attachments: hikari.UndefinedOr[collections.Sequence[hikari.Resourceish]] = hikari.UNDEFINED, component: hikari.UndefinedOr[hikari.api.ComponentBuilder] = hikari.UNDEFINED, @@ -809,13 +773,9 @@ async def respond( embed: hikari.UndefinedOr[hikari.Embed] = hikari.UNDEFINED, embeds: hikari.UndefinedOr[collections.Sequence[hikari.Embed]] = hikari.UNDEFINED, mentions_everyone: hikari.UndefinedOr[bool] = hikari.UNDEFINED, - user_mentions: typing.Union[ - hikari.SnowflakeishSequence[hikari.PartialUser], bool, hikari.UndefinedType - ] = hikari.UNDEFINED, - role_mentions: typing.Union[ - hikari.SnowflakeishSequence[hikari.PartialRole], bool, hikari.UndefinedType - ] = hikari.UNDEFINED, - ) -> typing.Optional[hikari.Message]: ... + user_mentions: hikari.SnowflakeishSequence[hikari.PartialUser] | bool | hikari.UndefinedType = hikari.UNDEFINED, + role_mentions: hikari.SnowflakeishSequence[hikari.PartialRole] | bool | hikari.UndefinedType = hikari.UNDEFINED, + ) -> hikari.Message | None: ... @abc.abstractmethod async def respond( @@ -823,7 +783,7 @@ async def respond( content: hikari.UndefinedOr[typing.Any] = hikari.UNDEFINED, *, ensure_result: bool = False, - delete_after: typing.Union[datetime.timedelta, float, int, None] = None, + delete_after: datetime.timedelta | float | int | None = None, attachment: hikari.UndefinedOr[hikari.Resourceish] = hikari.UNDEFINED, attachments: hikari.UndefinedOr[collections.Sequence[hikari.Resourceish]] = hikari.UNDEFINED, component: hikari.UndefinedOr[hikari.api.ComponentBuilder] = hikari.UNDEFINED, @@ -831,13 +791,9 @@ async def respond( embed: hikari.UndefinedOr[hikari.Embed] = hikari.UNDEFINED, embeds: hikari.UndefinedOr[collections.Sequence[hikari.Embed]] = hikari.UNDEFINED, mentions_everyone: hikari.UndefinedOr[bool] = hikari.UNDEFINED, - user_mentions: typing.Union[ - hikari.SnowflakeishSequence[hikari.PartialUser], bool, hikari.UndefinedType - ] = hikari.UNDEFINED, - role_mentions: typing.Union[ - hikari.SnowflakeishSequence[hikari.PartialRole], bool, hikari.UndefinedType - ] = hikari.UNDEFINED, - ) -> typing.Optional[hikari.Message]: + user_mentions: hikari.SnowflakeishSequence[hikari.PartialUser] | bool | hikari.UndefinedType = hikari.UNDEFINED, + role_mentions: hikari.SnowflakeishSequence[hikari.PartialRole] | bool | hikari.UndefinedType = hikari.UNDEFINED, + ) -> hikari.Message | None: """Respond to this context. Parameters @@ -946,7 +902,7 @@ class MessageContext(Context, abc.ABC): @property @abc.abstractmethod - def command(self) -> typing.Optional[MessageCommand[typing.Any]]: + def command(self) -> MessageCommand[typing.Any] | None: """Command that was invoked. !!! note @@ -971,7 +927,7 @@ def triggering_prefix(self) -> str: """Prefix that triggered the context.""" @abc.abstractmethod - def set_command(self, command: typing.Optional[MessageCommand[typing.Any]], /) -> Self: + def set_command(self, command: MessageCommand[typing.Any] | None, /) -> Self: raise NotImplementedError @abc.abstractmethod @@ -988,7 +944,7 @@ async def respond( content: hikari.UndefinedOr[typing.Any] = hikari.UNDEFINED, *, ensure_result: bool = True, - delete_after: typing.Union[datetime.timedelta, float, int, None] = None, + delete_after: datetime.timedelta | float | int | None = None, attachment: hikari.UndefinedOr[hikari.Resourceish] = hikari.UNDEFINED, attachments: hikari.UndefinedOr[collections.Sequence[hikari.Resourceish]] = hikari.UNDEFINED, component: hikari.UndefinedOr[hikari.api.ComponentBuilder] = hikari.UNDEFINED, @@ -998,15 +954,11 @@ async def respond( sticker: hikari.UndefinedOr[hikari.SnowflakeishOr[hikari.PartialSticker]] = hikari.UNDEFINED, stickers: hikari.UndefinedOr[hikari.SnowflakeishSequence[hikari.PartialSticker]] = hikari.UNDEFINED, tts: hikari.UndefinedOr[bool] = hikari.UNDEFINED, - reply: typing.Union[bool, hikari.SnowflakeishOr[hikari.PartialMessage], hikari.UndefinedType] = False, + reply: bool | hikari.SnowflakeishOr[hikari.PartialMessage] | hikari.UndefinedType = False, mentions_everyone: hikari.UndefinedOr[bool] = hikari.UNDEFINED, mentions_reply: hikari.UndefinedOr[bool] = hikari.UNDEFINED, - user_mentions: typing.Union[ - hikari.SnowflakeishSequence[hikari.PartialUser], bool, hikari.UndefinedType - ] = hikari.UNDEFINED, - role_mentions: typing.Union[ - hikari.SnowflakeishSequence[hikari.PartialRole], bool, hikari.UndefinedType - ] = hikari.UNDEFINED, + user_mentions: hikari.SnowflakeishSequence[hikari.PartialUser] | bool | hikari.UndefinedType = hikari.UNDEFINED, + role_mentions: hikari.SnowflakeishSequence[hikari.PartialRole] | bool | hikari.UndefinedType = hikari.UNDEFINED, ) -> hikari.Message: """Respond to this context. @@ -1128,12 +1080,12 @@ def name(self) -> str: @property @abc.abstractmethod - def type(self) -> typing.Union[hikari.OptionType, int]: + def type(self) -> hikari.OptionType | int: """Type of this option.""" @property @abc.abstractmethod - def value(self) -> typing.Union[str, hikari.Snowflake, int, bool, float]: + def value(self) -> str | hikari.Snowflake | int | bool | float: """Value provided for this option. !!! note @@ -1201,7 +1153,7 @@ def string(self) -> str: @abc.abstractmethod def resolve_value( self, - ) -> typing.Union[hikari.Attachment, hikari.InteractionChannel, hikari.InteractionMember, hikari.Role, hikari.User]: + ) -> hikari.Attachment | hikari.InteractionChannel | hikari.InteractionMember | hikari.Role | hikari.User: """Resolve this option to an object value. Returns @@ -1251,10 +1203,10 @@ def resolve_to_member(self) -> hikari.InteractionMember: ... @typing.overload @abc.abstractmethod - def resolve_to_member(self, *, default: _T) -> typing.Union[hikari.InteractionMember, _T]: ... + def resolve_to_member(self, *, default: _T) -> hikari.InteractionMember | _T: ... @abc.abstractmethod - def resolve_to_member(self, *, default: _T = ...) -> typing.Union[hikari.InteractionMember, _T]: + def resolve_to_member(self, *, default: _T = ...) -> hikari.InteractionMember | _T: """Resolve this option to a member object. Parameters @@ -1290,7 +1242,7 @@ def resolve_to_member(self, *, default: _T = ...) -> typing.Union[hikari.Interac """ @abc.abstractmethod - def resolve_to_mentionable(self) -> typing.Union[hikari.Role, hikari.User, hikari.Member]: + def resolve_to_mentionable(self) -> hikari.Role | hikari.User | hikari.Member: """Resolve this option to a mentionable object. Returns @@ -1322,7 +1274,7 @@ def resolve_to_role(self) -> hikari.Role: """ @abc.abstractmethod - def resolve_to_user(self) -> typing.Union[hikari.User, hikari.Member]: + def resolve_to_user(self) -> hikari.User | hikari.Member: """Resolve this option to a user object. !!! note @@ -1396,7 +1348,7 @@ def interaction(self) -> hikari.CommandInteraction: @property @abc.abstractmethod - def member(self) -> typing.Optional[hikari.InteractionMember]: + def member(self) -> hikari.InteractionMember | None: """Object of the member that triggered this command if this is in a guild.""" @property @@ -1421,8 +1373,8 @@ def set_ephemeral_default(self, state: bool, /) -> Self: async def defer( self, *, - ephemeral: typing.Optional[bool] = None, - flags: typing.Union[hikari.UndefinedType, int, hikari.MessageFlag] = hikari.UNDEFINED, + ephemeral: bool | None = None, + flags: hikari.UndefinedType | int | hikari.MessageFlag = hikari.UNDEFINED, ) -> None: """Defer the initial response for this context. @@ -1454,8 +1406,8 @@ async def create_followup( self, content: hikari.UndefinedOr[typing.Any] = hikari.UNDEFINED, *, - delete_after: typing.Union[datetime.timedelta, float, int, None] = None, - ephemeral: typing.Optional[bool] = None, + delete_after: datetime.timedelta | float | int | None = None, + ephemeral: bool | None = None, attachment: hikari.UndefinedOr[hikari.Resourceish] = hikari.UNDEFINED, attachments: hikari.UndefinedOr[collections.Sequence[hikari.Resourceish]] = hikari.UNDEFINED, component: hikari.UndefinedOr[hikari.api.ComponentBuilder] = hikari.UNDEFINED, @@ -1463,14 +1415,10 @@ async def create_followup( embed: hikari.UndefinedOr[hikari.Embed] = hikari.UNDEFINED, embeds: hikari.UndefinedOr[collections.Sequence[hikari.Embed]] = hikari.UNDEFINED, mentions_everyone: hikari.UndefinedOr[bool] = hikari.UNDEFINED, - user_mentions: typing.Union[ - hikari.SnowflakeishSequence[hikari.PartialUser], bool, hikari.UndefinedType - ] = hikari.UNDEFINED, - role_mentions: typing.Union[ - hikari.SnowflakeishSequence[hikari.PartialRole], bool, hikari.UndefinedType - ] = hikari.UNDEFINED, + user_mentions: hikari.SnowflakeishSequence[hikari.PartialUser] | bool | hikari.UndefinedType = hikari.UNDEFINED, + role_mentions: hikari.SnowflakeishSequence[hikari.PartialRole] | bool | hikari.UndefinedType = hikari.UNDEFINED, tts: hikari.UndefinedOr[bool] = hikari.UNDEFINED, - flags: typing.Union[hikari.UndefinedType, int, hikari.MessageFlag] = hikari.UNDEFINED, + flags: hikari.UndefinedType | int | hikari.MessageFlag = hikari.UNDEFINED, ) -> hikari.Message: """Create a followup response for this context. @@ -1575,8 +1523,8 @@ async def create_initial_response( self, content: hikari.UndefinedOr[typing.Any] = hikari.UNDEFINED, *, - delete_after: typing.Union[datetime.timedelta, float, int, None] = None, - ephemeral: typing.Optional[bool] = None, + delete_after: datetime.timedelta | float | int | None = None, + ephemeral: bool | None = None, attachment: hikari.UndefinedOr[hikari.Resourceish] = hikari.UNDEFINED, attachments: hikari.UndefinedOr[collections.Sequence[hikari.Resourceish]] = hikari.UNDEFINED, component: hikari.UndefinedOr[hikari.api.ComponentBuilder] = hikari.UNDEFINED, @@ -1584,13 +1532,9 @@ async def create_initial_response( embed: hikari.UndefinedOr[hikari.Embed] = hikari.UNDEFINED, embeds: hikari.UndefinedOr[collections.Sequence[hikari.Embed]] = hikari.UNDEFINED, mentions_everyone: hikari.UndefinedOr[bool] = hikari.UNDEFINED, - user_mentions: typing.Union[ - hikari.SnowflakeishSequence[hikari.PartialUser], bool, hikari.UndefinedType - ] = hikari.UNDEFINED, - role_mentions: typing.Union[ - hikari.SnowflakeishSequence[hikari.PartialRole], bool, hikari.UndefinedType - ] = hikari.UNDEFINED, - flags: typing.Union[int, hikari.MessageFlag, hikari.UndefinedType] = hikari.UNDEFINED, + user_mentions: hikari.SnowflakeishSequence[hikari.PartialUser] | bool | hikari.UndefinedType = hikari.UNDEFINED, + role_mentions: hikari.SnowflakeishSequence[hikari.PartialRole] | bool | hikari.UndefinedType = hikari.UNDEFINED, + flags: int | hikari.MessageFlag | hikari.UndefinedType = hikari.UNDEFINED, tts: hikari.UndefinedOr[bool] = hikari.UNDEFINED, ) -> None: """Create the initial response for this context. @@ -1747,7 +1691,7 @@ class MenuContext(AppCommandContext, abc.ABC): @property @abc.abstractmethod - def command(self) -> typing.Optional[MenuCommand[typing.Any, typing.Any]]: + def command(self) -> MenuCommand[typing.Any, typing.Any] | None: """Command that was invoked. !!! note @@ -1763,7 +1707,7 @@ def target_id(self) -> hikari.Snowflake: @property @abc.abstractmethod - def target(self) -> typing.Union[hikari.InteractionMember, hikari.User, hikari.Message]: + def target(self) -> hikari.InteractionMember | hikari.User | hikari.Message: """Object of the entity this menu targets.""" @property @@ -1772,7 +1716,7 @@ def type(self) -> typing.Literal[hikari.CommandType.MESSAGE, hikari.CommandType. """The type of context menu this context is for.""" @abc.abstractmethod - def set_command(self, command: typing.Optional[MenuCommand[typing.Any, typing.Any]], /) -> Self: + def set_command(self, command: MenuCommand[typing.Any, typing.Any] | None, /) -> Self: """Set the command for this context. Parameters @@ -1787,10 +1731,10 @@ def resolve_to_member(self) -> hikari.InteractionMember: ... @typing.overload @abc.abstractmethod - def resolve_to_member(self, *, default: _T) -> typing.Union[hikari.InteractionMember, _T]: ... + def resolve_to_member(self, *, default: _T) -> hikari.InteractionMember | _T: ... @abc.abstractmethod - def resolve_to_member(self, *, default: _T = ...) -> typing.Union[hikari.InteractionMember, _T]: + def resolve_to_member(self, *, default: _T = ...) -> hikari.InteractionMember | _T: """Resolve a user context menu context to a member object. Returns @@ -1825,7 +1769,7 @@ def resolve_to_message(self) -> hikari.Message: """ @abc.abstractmethod - def resolve_to_user(self) -> typing.Union[hikari.User, hikari.Member]: + def resolve_to_user(self) -> hikari.User | hikari.Member: """Resolve a user context menu context to a user object. Returns @@ -1847,7 +1791,7 @@ class SlashContext(AppCommandContext, abc.ABC): @property @abc.abstractmethod - def command(self) -> typing.Optional[BaseSlashCommand]: + def command(self) -> BaseSlashCommand | None: """Command that was invoked. !!! note @@ -1867,7 +1811,7 @@ def type(self) -> typing.Literal[hikari.CommandType.SLASH]: """Type of application command this context is for.""" @abc.abstractmethod - def set_command(self, command: typing.Optional[BaseSlashCommand], /) -> Self: + def set_command(self, command: BaseSlashCommand | None, /) -> Self: """Set the command for this context. Parameters @@ -1894,7 +1838,7 @@ def channel_id(self) -> hikari.Snowflake: @property @abc.abstractmethod - def cache(self) -> typing.Optional[hikari.api.Cache]: + def cache(self) -> hikari.api.Cache | None: """Hikari cache instance this context's client was initialised with.""" @property @@ -1913,7 +1857,7 @@ def created_at(self) -> datetime.datetime: @property @abc.abstractmethod - def events(self) -> typing.Optional[hikari.api.EventManager]: + def events(self) -> hikari.api.EventManager | None: """Object of the event manager this context's client was initialised with.""" @property @@ -1923,7 +1867,7 @@ def focused(self) -> hikari.AutocompleteInteractionOption: @property @abc.abstractmethod - def guild_id(self) -> typing.Optional[hikari.Snowflake]: + def guild_id(self) -> hikari.Snowflake | None: """ID of the guild this autocomplete was triggered in. Will be [None][] for all DM autocomplete executions. @@ -1931,7 +1875,7 @@ def guild_id(self) -> typing.Optional[hikari.Snowflake]: @property @abc.abstractmethod - def member(self) -> typing.Optional[hikari.Member]: + def member(self) -> hikari.Member | None: """Guild member object of this autocomplete's author. Will be [None][] for DM autocomplete executions. @@ -1939,7 +1883,7 @@ def member(self) -> typing.Optional[hikari.Member]: @property @abc.abstractmethod - def server(self) -> typing.Optional[hikari.api.InteractionServer]: + def server(self) -> hikari.api.InteractionServer | None: """Object of the Hikari interaction server provided for this context's client.""" @property @@ -1949,7 +1893,7 @@ def rest(self) -> hikari.api.RESTClient: @property @abc.abstractmethod - def shard(self) -> typing.Optional[hikari.api.GatewayShard]: + def shard(self) -> hikari.api.GatewayShard | None: """Shard that triggered the context. !!! note @@ -1959,12 +1903,12 @@ def shard(self) -> typing.Optional[hikari.api.GatewayShard]: @property @abc.abstractmethod - def shards(self) -> typing.Optional[hikari.ShardAware]: + def shards(self) -> hikari.ShardAware | None: """Object of the Hikari shard manager this context's client was initialised with.""" @property @abc.abstractmethod - def voice(self) -> typing.Optional[hikari.api.VoiceComponent]: + def voice(self) -> hikari.api.VoiceComponent | None: """Object of the Hikari voice component this context's client was initialised with.""" @property @@ -2022,7 +1966,7 @@ async def fetch_channel(self) -> hikari.TextableChannel: """ @abc.abstractmethod - async def fetch_guild(self) -> typing.Optional[hikari.Guild]: + async def fetch_guild(self) -> hikari.Guild | None: """Fetch the guild the context was invoked in. !!! note @@ -2054,7 +1998,7 @@ async def fetch_guild(self) -> typing.Optional[hikari.Guild]: """ @abc.abstractmethod - def get_channel(self) -> typing.Optional[hikari.TextableGuildChannel]: + def get_channel(self) -> hikari.TextableGuildChannel | None: """Retrieve the channel the context was invoked in from the cache. !!! note @@ -2071,7 +2015,7 @@ def get_channel(self) -> typing.Optional[hikari.TextableGuildChannel]: """ @abc.abstractmethod - def get_guild(self) -> typing.Optional[hikari.Guild]: + def get_guild(self) -> hikari.Guild | None: """Fetch the guild that the context was invoked in. !!! note @@ -2089,9 +2033,9 @@ def get_guild(self) -> typing.Optional[hikari.Guild]: @abc.abstractmethod async def set_choices( self, - choices: typing.Union[ - collections.Mapping[str, _AutocompleteValueT], collections.Iterable[tuple[str, _AutocompleteValueT]] - ] = ..., + choices: ( + collections.Mapping[str, _AutocompleteValueT] | collections.Iterable[tuple[str, _AutocompleteValueT]] + ) = ..., /, **kwargs: _AutocompleteValueT, ) -> None: @@ -2480,25 +2424,25 @@ async def trigger_error( exception: Exception, /, *, - hooks: typing.Optional[collections.Set[Hooks[_ContextT_contra]]] = None, + hooks: collections.Set[Hooks[_ContextT_contra]] | None = None, ) -> int: raise NotImplementedError @abc.abstractmethod async def trigger_post_execution( - self, ctx: _ContextT_contra, /, *, hooks: typing.Optional[collections.Set[Hooks[_ContextT_contra]]] = None + self, ctx: _ContextT_contra, /, *, hooks: collections.Set[Hooks[_ContextT_contra]] | None = None ) -> None: raise NotImplementedError @abc.abstractmethod async def trigger_pre_execution( - self, ctx: _ContextT_contra, /, *, hooks: typing.Optional[collections.Set[Hooks[_ContextT_contra]]] = None + self, ctx: _ContextT_contra, /, *, hooks: collections.Set[Hooks[_ContextT_contra]] | None = None ) -> None: raise NotImplementedError @abc.abstractmethod async def trigger_success( - self, ctx: _ContextT_contra, /, *, hooks: typing.Optional[collections.Set[Hooks[_ContextT_contra]]] = None + self, ctx: _ContextT_contra, /, *, hooks: collections.Set[Hooks[_ContextT_contra]] | None = None ) -> None: raise NotImplementedError @@ -2528,12 +2472,12 @@ def checks(self) -> collections.Collection[CheckSig[_ContextT_co]]: @property @abc.abstractmethod - def component(self) -> typing.Optional[Component]: + def component(self) -> Component | None: """Component that the command is registered with.""" @property @abc.abstractmethod - def hooks(self) -> typing.Optional[Hooks[_ContextT_co]]: + def hooks(self) -> Hooks[_ContextT_co] | None: """Hooks that are triggered when the command is executed.""" @property @@ -2565,7 +2509,7 @@ def copy(self) -> Self: """ @abc.abstractmethod - def set_hooks(self, hooks: typing.Optional[Hooks[_ContextT_co]], /) -> Self: + def set_hooks(self, hooks: Hooks[_ContextT_co] | None, /) -> Self: """Set the hooks that are triggered when the command is executed. Parameters @@ -2639,7 +2583,7 @@ class AppCommand(ExecutableCommand[_AppCommandContextT]): @property @abc.abstractmethod - def default_member_permissions(self) -> typing.Optional[hikari.Permissions]: + def default_member_permissions(self) -> hikari.Permissions | None: """The default guild member permissions required to use this command. !!! warning @@ -2652,7 +2596,7 @@ def default_member_permissions(self) -> typing.Optional[hikari.Permissions]: @property @abc.abstractmethod - def defaults_to_ephemeral(self) -> typing.Optional[bool]: + def defaults_to_ephemeral(self) -> bool | None: """Whether contexts executed by this command should default to ephemeral responses. This effects calls to @@ -2669,7 +2613,7 @@ def defaults_to_ephemeral(self) -> typing.Optional[bool]: @property @abc.abstractmethod - def is_dm_enabled(self) -> typing.Optional[bool]: + def is_dm_enabled(self) -> bool | None: """Whether this command is enabled in DM contexts. !!! note @@ -2692,7 +2636,7 @@ def is_global(self) -> bool: """ @property - def is_nsfw(self) -> typing.Optional[bool]: + def is_nsfw(self) -> bool | None: """Whether a command should only be accessible in channels marked as NSFW.""" @property @@ -2702,12 +2646,12 @@ def name(self) -> str: @property @abc.abstractmethod - def tracked_command(self) -> typing.Optional[hikari.PartialCommand]: + def tracked_command(self) -> hikari.PartialCommand | None: """Object of the actual command this object tracks if set.""" @property @abc.abstractmethod - def tracked_command_id(self) -> typing.Optional[hikari.Snowflake]: + def tracked_command_id(self) -> hikari.Snowflake | None: """ID of the actual command this object tracks if set.""" @property @@ -2716,7 +2660,7 @@ def type(self) -> hikari.CommandType: """The type of this application command.""" @abc.abstractmethod - def build(self, *, component: typing.Optional[Component] = None) -> hikari.api.CommandBuilder: + def build(self, *, component: Component | None = None) -> hikari.api.CommandBuilder: """Get a builder object for this command. Parameters @@ -2740,11 +2684,7 @@ async def check_context(self, ctx: _AppCommandContextT, /) -> bool: @abc.abstractmethod async def execute( - self, - ctx: _AppCommandContextT, - /, - *, - hooks: typing.Optional[collections.MutableSet[Hooks[_AppCommandContextT]]] = None, + self, ctx: _AppCommandContextT, /, *, hooks: collections.MutableSet[Hooks[_AppCommandContextT]] | None = None ) -> None: raise NotImplementedError @@ -2771,12 +2711,12 @@ class BaseSlashCommand(AppCommand[SlashContext], abc.ABC): @property @abc.abstractmethod - def parent(self) -> typing.Optional[SlashCommandGroup]: + def parent(self) -> SlashCommandGroup | None: """Object of the group this command is in.""" @property @abc.abstractmethod - def tracked_command(self) -> typing.Optional[hikari.SlashCommand]: + def tracked_command(self) -> hikari.SlashCommand | None: """Object of the actual command this object tracks if set.""" @property @@ -2785,7 +2725,7 @@ def type(self) -> typing.Literal[hikari.CommandType.SLASH]: """The type of this command.""" @abc.abstractmethod - def build(self, *, component: typing.Optional[Component] = None) -> hikari.api.SlashCommandBuilder: + def build(self, *, component: Component | None = None) -> hikari.api.SlashCommandBuilder: """Get a builder object for this command. Parameters @@ -2804,7 +2744,7 @@ def build(self, *, component: typing.Optional[Component] = None) -> hikari.api.S """ @abc.abstractmethod - def copy(self, *, parent: typing.Optional[SlashCommandGroup] = None) -> Self: + def copy(self, *, parent: SlashCommandGroup | None = None) -> Self: """Create a copy of this command. Parameters @@ -2819,7 +2759,7 @@ def copy(self, *, parent: typing.Optional[SlashCommandGroup] = None) -> Self: """ @abc.abstractmethod - def set_parent(self, parent: typing.Optional[SlashCommandGroup], /) -> Self: + def set_parent(self, parent: SlashCommandGroup | None, /) -> Self: raise NotImplementedError @abc.abstractmethod @@ -2828,15 +2768,15 @@ async def execute( ctx: SlashContext, /, *, - option: typing.Optional[hikari.CommandInteractionOption] = None, - hooks: typing.Optional[collections.MutableSet[SlashHooks]] = None, + option: hikari.CommandInteractionOption | None = None, + hooks: collections.MutableSet[SlashHooks] | None = None, ) -> None: raise NotImplementedError ... @abc.abstractmethod async def execute_autocomplete( - self, ctx: AutocompleteContext, /, *, option: typing.Optional[hikari.AutocompleteInteractionOption] = None + self, ctx: AutocompleteContext, /, *, option: hikari.AutocompleteInteractionOption | None = None ) -> None: ... @@ -2883,11 +2823,11 @@ def type(self) -> _MenuTypeT: @property @abc.abstractmethod - def tracked_command(self) -> typing.Optional[hikari.ContextMenuCommand]: + def tracked_command(self) -> hikari.ContextMenuCommand | None: """Object of the actual command this object tracks if set.""" @abc.abstractmethod - def build(self, *, component: typing.Optional[Component] = None) -> hikari.api.ContextMenuCommandBuilder: + def build(self, *, component: Component | None = None) -> hikari.api.ContextMenuCommandBuilder: """Get a builder object for this command. Parameters @@ -3059,16 +2999,16 @@ def names(self) -> collections.Collection[str]: @property @abc.abstractmethod - def parent(self) -> typing.Optional[MessageCommandGroup[typing.Any]]: + def parent(self) -> MessageCommandGroup[typing.Any] | None: """Parent group of this command if applicable.""" @property @abc.abstractmethod - def parser(self) -> typing.Optional[MessageParser]: + def parser(self) -> MessageParser | None: """Parser for this command.""" @abc.abstractmethod - def set_parent(self, parent: typing.Optional[MessageCommandGroup[typing.Any]], /) -> Self: + def set_parent(self, parent: MessageCommandGroup[typing.Any] | None, /) -> Self: """Set the parent of this command. Parameters @@ -3104,7 +3044,7 @@ def set_parser(self, parser: MessageParser, /) -> Self: """ @abc.abstractmethod - def copy(self, *, parent: typing.Optional[MessageCommandGroup[typing.Any]] = None) -> Self: + def copy(self, *, parent: MessageCommandGroup[typing.Any] | None = None) -> Self: """Create a copy of this command. Parameters @@ -3124,7 +3064,7 @@ async def check_context(self, ctx: MessageContext, /) -> bool: @abc.abstractmethod async def execute( - self, ctx: MessageContext, /, *, hooks: typing.Optional[collections.MutableSet[Hooks[MessageContext]]] = None + self, ctx: MessageContext, /, *, hooks: collections.MutableSet[Hooks[MessageContext]] | None = None ) -> None: raise NotImplementedError @@ -3206,12 +3146,12 @@ class Component(abc.ABC): @property @abc.abstractmethod - def client(self) -> typing.Optional[Client]: + def client(self) -> Client | None: """Tanjun client this component is bound to.""" @property @abc.abstractmethod - def default_app_cmd_permissions(self) -> typing.Optional[hikari.Permissions]: + def default_app_cmd_permissions(self) -> hikari.Permissions | None: """Default required guild member permissions for the commands in this component. This may be overridden by @@ -3224,7 +3164,7 @@ def default_app_cmd_permissions(self) -> typing.Optional[hikari.Permissions]: @property @abc.abstractmethod - def defaults_to_ephemeral(self) -> typing.Optional[bool]: + def defaults_to_ephemeral(self) -> bool | None: """Whether slash contexts executed in this component should default to ephemeral responses. This effects calls to @@ -3243,7 +3183,7 @@ def defaults_to_ephemeral(self) -> typing.Optional[bool]: @property @abc.abstractmethod - def dms_enabled_for_app_cmds(self) -> typing.Optional[bool]: + def dms_enabled_for_app_cmds(self) -> bool | None: """Whether application commands in this component should be enabled in DMs. !!! note @@ -3255,7 +3195,7 @@ def dms_enabled_for_app_cmds(self) -> typing.Optional[bool]: @property @abc.abstractmethod - def is_case_sensitive(self) -> typing.Optional[bool]: + def is_case_sensitive(self) -> bool | None: """Whether this component should treat message command names case sensitive in search. If this is `None` then the client's case sensitivity will be used. @@ -3263,7 +3203,7 @@ def is_case_sensitive(self) -> typing.Optional[bool]: @property @abc.abstractmethod - def loop(self) -> typing.Optional[asyncio.AbstractEventLoop]: + def loop(self) -> asyncio.AbstractEventLoop | None: """The asyncio loop this client is bound to if it has been opened.""" @property @@ -3364,8 +3304,8 @@ def with_menu_command(self, /, *, copy: bool = False) -> collections.Callable[[_ @abc.abstractmethod def with_menu_command( - self, command: typing.Optional[_MenuCommandT] = None, /, *, copy: bool = False - ) -> typing.Union[_MenuCommandT, collections.Callable[[_MenuCommandT], _MenuCommandT]]: + self, command: _MenuCommandT | None = None, /, *, copy: bool = False + ) -> _MenuCommandT | collections.Callable[[_MenuCommandT], _MenuCommandT]: """Add a menu command to this component through a decorator call. Parameters @@ -3428,8 +3368,8 @@ def with_slash_command( @abc.abstractmethod def with_slash_command( - self, command: typing.Optional[_BaseSlashCommandT] = None, /, *, copy: bool = False - ) -> typing.Union[_BaseSlashCommandT, collections.Callable[[_BaseSlashCommandT], _BaseSlashCommandT]]: + self, command: _BaseSlashCommandT | None = None, /, *, copy: bool = False + ) -> _BaseSlashCommandT | collections.Callable[[_BaseSlashCommandT], _BaseSlashCommandT]: """Add a slash command to this component through a decorator call. Parameters @@ -3492,8 +3432,8 @@ def with_message_command( @abc.abstractmethod def with_message_command( - self, command: typing.Optional[_MessageCommandT] = None, /, *, copy: bool = False - ) -> typing.Union[_MessageCommandT, collections.Callable[[_MessageCommandT], _MessageCommandT]]: + self, command: _MessageCommandT | None = None, /, *, copy: bool = False + ) -> _MessageCommandT | collections.Callable[[_MessageCommandT], _MessageCommandT]: """Add a message command to this component through a decorator call. Parameters @@ -3632,7 +3572,7 @@ def check_slash_name(self, name: str, /) -> collections.Iterator[BaseSlashComman """ @abc.abstractmethod - def execute_autocomplete(self, ctx: AutocompleteContext, /) -> typing.Optional[_CoroT[None]]: + def execute_autocomplete(self, ctx: AutocompleteContext, /) -> _CoroT[None] | None: """Execute an autocomplete context. !!! note @@ -3657,8 +3597,8 @@ def execute_autocomplete(self, ctx: AutocompleteContext, /) -> typing.Optional[_ @abc.abstractmethod async def execute_menu( - self, ctx: MenuContext, /, *, hooks: typing.Optional[collections.MutableSet[MenuHooks]] = None - ) -> typing.Optional[_CoroT[None]]: + self, ctx: MenuContext, /, *, hooks: collections.MutableSet[MenuHooks] | None = None + ) -> _CoroT[None] | None: """Execute a menu context. Parameters @@ -3689,8 +3629,8 @@ async def execute_menu( @abc.abstractmethod async def execute_slash( - self, ctx: SlashContext, /, *, hooks: typing.Optional[collections.MutableSet[SlashHooks]] = None - ) -> typing.Optional[_CoroT[None]]: + self, ctx: SlashContext, /, *, hooks: collections.MutableSet[SlashHooks] | None = None + ) -> _CoroT[None] | None: """Execute a slash context. Parameters @@ -3721,7 +3661,7 @@ async def execute_slash( @abc.abstractmethod async def execute_message( - self, ctx: MessageContext, /, *, hooks: typing.Optional[collections.MutableSet[MessageHooks]] = None + self, ctx: MessageContext, /, *, hooks: collections.MutableSet[MessageHooks] | None = None ) -> bool: """Execute a message context. @@ -3862,7 +3802,7 @@ class Client(abc.ABC): @property @abc.abstractmethod - def cache(self) -> typing.Optional[hikari.api.Cache]: + def cache(self) -> hikari.api.Cache | None: """Hikari cache instance this command client was initialised with.""" @property @@ -3921,7 +3861,7 @@ def dms_enabled_for_app_cmds(self) -> bool: @property @abc.abstractmethod - def events(self) -> typing.Optional[hikari.api.EventManager]: + def events(self) -> hikari.api.EventManager | None: """Object of the event manager this client was initialised with. This is used for executing message commands if set. @@ -3951,7 +3891,7 @@ def listeners( @property @abc.abstractmethod - def loop(self) -> typing.Optional[asyncio.AbstractEventLoop]: + def loop(self) -> asyncio.AbstractEventLoop | None: """The loop this client is bound to if it's alive.""" @property @@ -3980,7 +3920,7 @@ def rest(self) -> hikari.api.RESTClient: @property @abc.abstractmethod - def server(self) -> typing.Optional[hikari.api.InteractionServer]: + def server(self) -> hikari.api.InteractionServer | None: """Object of the Hikari interaction server provided for this client. This is used for executing application commands if set. @@ -3988,19 +3928,19 @@ def server(self) -> typing.Optional[hikari.api.InteractionServer]: @property @abc.abstractmethod - def shards(self) -> typing.Optional[hikari.ShardAware]: + def shards(self) -> hikari.ShardAware | None: """Object of the Hikari shard manager this client was initialised with.""" @property @abc.abstractmethod - def voice(self) -> typing.Optional[hikari.api.VoiceComponent]: + def voice(self) -> hikari.api.VoiceComponent | None: """Object of the Hikari voice component this client was initialised with.""" @abc.abstractmethod async def clear_application_commands( self, *, - application: typing.Optional[hikari.SnowflakeishOr[hikari.PartialApplication]] = None, + application: hikari.SnowflakeishOr[hikari.PartialApplication] | None = None, guild: hikari.UndefinedOr[hikari.SnowflakeishOr[hikari.PartialGuild]] = hikari.UNDEFINED, ) -> None: """Clear the commands declared either globally or for a specific guild. @@ -4026,12 +3966,12 @@ async def clear_application_commands( @abc.abstractmethod async def declare_global_commands( self, - command_ids: typing.Optional[collections.Mapping[str, hikari.SnowflakeishOr[hikari.PartialCommand]]] = None, + command_ids: collections.Mapping[str, hikari.SnowflakeishOr[hikari.PartialCommand]] | None = None, *, - application: typing.Optional[hikari.SnowflakeishOr[hikari.PartialApplication]] = None, + application: hikari.SnowflakeishOr[hikari.PartialApplication] | None = None, guild: hikari.UndefinedOr[hikari.SnowflakeishOr[hikari.PartialGuild]] = hikari.UNDEFINED, - message_ids: typing.Optional[collections.Mapping[str, hikari.SnowflakeishOr[hikari.PartialCommand]]] = None, - user_ids: typing.Optional[collections.Mapping[str, hikari.SnowflakeishOr[hikari.PartialCommand]]] = None, + message_ids: collections.Mapping[str, hikari.SnowflakeishOr[hikari.PartialCommand]] | None = None, + user_ids: collections.Mapping[str, hikari.SnowflakeishOr[hikari.PartialCommand]] | None = None, force: bool = False, ) -> collections.Sequence[hikari.PartialCommand]: """Set the global application commands for a bot based on the loaded components. @@ -4089,9 +4029,9 @@ async def declare_application_command( self, command: BaseSlashCommand, /, - command_id: typing.Optional[hikari.Snowflakeish] = None, + command_id: hikari.Snowflakeish | None = None, *, - application: typing.Optional[hikari.SnowflakeishOr[hikari.PartialApplication]] = None, + application: hikari.SnowflakeishOr[hikari.PartialApplication] | None = None, guild: hikari.UndefinedOr[hikari.SnowflakeishOr[hikari.PartialGuild]] = hikari.UNDEFINED, ) -> hikari.SlashCommand: ... @@ -4101,9 +4041,9 @@ async def declare_application_command( self, command: MenuCommand[typing.Any, typing.Any], /, - command_id: typing.Optional[hikari.Snowflakeish] = None, + command_id: hikari.Snowflakeish | None = None, *, - application: typing.Optional[hikari.SnowflakeishOr[hikari.PartialApplication]] = None, + application: hikari.SnowflakeishOr[hikari.PartialApplication] | None = None, guild: hikari.UndefinedOr[hikari.SnowflakeishOr[hikari.PartialGuild]] = hikari.UNDEFINED, ) -> hikari.ContextMenuCommand: ... @@ -4113,9 +4053,9 @@ async def declare_application_command( self, command: AppCommand[typing.Any], /, - command_id: typing.Optional[hikari.Snowflakeish] = None, + command_id: hikari.Snowflakeish | None = None, *, - application: typing.Optional[hikari.SnowflakeishOr[hikari.PartialApplication]] = None, + application: hikari.SnowflakeishOr[hikari.PartialApplication] | None = None, guild: hikari.UndefinedOr[hikari.SnowflakeishOr[hikari.PartialGuild]] = hikari.UNDEFINED, ) -> hikari.PartialCommand: ... @@ -4124,9 +4064,9 @@ async def declare_application_command( self, command: AppCommand[typing.Any], /, - command_id: typing.Optional[hikari.Snowflakeish] = None, + command_id: hikari.Snowflakeish | None = None, *, - application: typing.Optional[hikari.SnowflakeishOr[hikari.PartialApplication]] = None, + application: hikari.SnowflakeishOr[hikari.PartialApplication] | None = None, guild: hikari.UndefinedOr[hikari.SnowflakeishOr[hikari.PartialGuild]] = hikari.UNDEFINED, ) -> hikari.PartialCommand: """Declare a single slash command for a bot. @@ -4161,14 +4101,14 @@ async def declare_application_command( @abc.abstractmethod async def declare_application_commands( self, - commands: collections.Iterable[typing.Union[AppCommand[typing.Any], hikari.api.CommandBuilder]], + commands: collections.Iterable[AppCommand[typing.Any] | hikari.api.CommandBuilder], /, - command_ids: typing.Optional[collections.Mapping[str, hikari.SnowflakeishOr[hikari.PartialCommand]]] = None, + command_ids: collections.Mapping[str, hikari.SnowflakeishOr[hikari.PartialCommand]] | None = None, *, - application: typing.Optional[hikari.SnowflakeishOr[hikari.PartialApplication]] = None, + application: hikari.SnowflakeishOr[hikari.PartialApplication] | None = None, guild: hikari.UndefinedOr[hikari.SnowflakeishOr[hikari.PartialGuild]] = hikari.UNDEFINED, - message_ids: typing.Optional[collections.Mapping[str, hikari.SnowflakeishOr[hikari.PartialCommand]]] = None, - user_ids: typing.Optional[collections.Mapping[str, hikari.SnowflakeishOr[hikari.PartialCommand]]] = None, + message_ids: collections.Mapping[str, hikari.SnowflakeishOr[hikari.PartialCommand]] | None = None, + user_ids: collections.Mapping[str, hikari.SnowflakeishOr[hikari.PartialCommand]] | None = None, force: bool = False, ) -> collections.Sequence[hikari.PartialCommand]: """Declare a collection of slash commands for a bot. @@ -4264,7 +4204,7 @@ def add_component(self, component: Component, /) -> Self: """ @abc.abstractmethod - def get_component_by_name(self, name: str, /) -> typing.Optional[Component]: + def get_component_by_name(self, name: str, /) -> Component | None: """Get a component from this client by name. Parameters @@ -4320,7 +4260,7 @@ def remove_component_by_name(self, name: str, /) -> Self: """ @abc.abstractmethod - def add_client_callback(self, name: typing.Union[str, ClientCallbackNames], /, *callbacks: MetaEventSig) -> Self: + def add_client_callback(self, name: str | ClientCallbackNames, /, *callbacks: MetaEventSig) -> Self: """Add a client callback. Parameters @@ -4343,9 +4283,7 @@ def add_client_callback(self, name: typing.Union[str, ClientCallbackNames], /, * """ @abc.abstractmethod - async def dispatch_client_callback( - self, name: typing.Union[str, ClientCallbackNames], /, *args: typing.Any - ) -> None: + async def dispatch_client_callback(self, name: str | ClientCallbackNames, /, *args: typing.Any) -> None: """Dispatch a client callback. Parameters @@ -4362,9 +4300,7 @@ async def dispatch_client_callback( """ @abc.abstractmethod - def get_client_callbacks( - self, name: typing.Union[str, ClientCallbackNames], / - ) -> collections.Collection[MetaEventSig]: + def get_client_callbacks(self, name: str | ClientCallbackNames, /) -> collections.Collection[MetaEventSig]: """Get a collection of the callbacks registered for a specific name. Parameters @@ -4381,7 +4317,7 @@ def get_client_callbacks( """ @abc.abstractmethod - def remove_client_callback(self, name: typing.Union[str, ClientCallbackNames], callback: MetaEventSig, /) -> Self: + def remove_client_callback(self, name: str | ClientCallbackNames, callback: MetaEventSig, /) -> Self: """Remove a client callback. Parameters @@ -4408,7 +4344,7 @@ def remove_client_callback(self, name: typing.Union[str, ClientCallbackNames], c @abc.abstractmethod def with_client_callback( - self, name: typing.Union[str, ClientCallbackNames], / + self, name: str | ClientCallbackNames, / ) -> collections.Callable[[_MetaEventSigT], _MetaEventSigT]: """Add a client callback through a decorator call. @@ -4551,12 +4487,12 @@ def iter_menu_commands( @typing.overload @abc.abstractmethod def iter_menu_commands( - self, *, global_only: bool = False, type: typing.Optional[hikari.CommandType] = None # noqa: A002 + self, *, global_only: bool = False, type: hikari.CommandType | None = None # noqa: A002 ) -> collections.Iterator[MenuCommand[typing.Any, typing.Any]]: ... @abc.abstractmethod def iter_menu_commands( - self, *, global_only: bool = False, type: typing.Optional[hikari.CommandType] = None # noqa: A002 + self, *, global_only: bool = False, type: hikari.CommandType | None = None # noqa: A002 ) -> collections.Iterator[MenuCommand[typing.Any, typing.Any]]: """Iterator over the menu commands registered to this client. @@ -4640,9 +4576,7 @@ def check_slash_name(self, name: str, /) -> collections.Iterator[BaseSlashComman """ @abc.abstractmethod - def load_directory( - self, directory: typing.Union[str, pathlib.Path], /, *, namespace: typing.Optional[str] = None - ) -> Self: + def load_directory(self, directory: str | pathlib.Path, /, *, namespace: str | None = None) -> Self: r"""Load entities into this client from the modules in a directory. The same loading rules for [Client.load_modules][tanjun.abc.Client.load_modules] @@ -4684,9 +4618,7 @@ def load_directory( """ @abc.abstractmethod - async def load_directory_async( - self, directory: typing.Union[str, pathlib.Path], /, *, namespace: typing.Optional[str] = None - ) -> None: + async def load_directory_async(self, directory: str | pathlib.Path, /, *, namespace: str | None = None) -> None: """Asynchronous variant of [Client.load_directory][tanjun.abc.Client.load_directory]. Unlike [Client.load_directory][tanjun.abc.Client.load_directory], this @@ -4697,7 +4629,7 @@ async def load_directory_async( """ @abc.abstractmethod - def load_modules(self, *modules: typing.Union[str, pathlib.Path]) -> Self: + def load_modules(self, *modules: str | pathlib.Path) -> Self: r"""Load entities into this client from modules based on present loaders. !!! note @@ -4757,7 +4689,7 @@ def load_module(client: tanjun.Client) -> None: """ @abc.abstractmethod - async def load_modules_async(self, *modules: typing.Union[str, pathlib.Path]) -> None: + async def load_modules_async(self, *modules: str | pathlib.Path) -> None: """Asynchronous variant of [Client.load_modules][tanjun.abc.Client.load_modules]. Unlike [Client.load_modules][tanjun.abc.Client.load_modules], this @@ -4768,7 +4700,7 @@ async def load_modules_async(self, *modules: typing.Union[str, pathlib.Path]) -> """ @abc.abstractmethod - def unload_modules(self, *modules: typing.Union[str, pathlib.Path]) -> Self: + def unload_modules(self, *modules: str | pathlib.Path) -> Self: r"""Unload entities from this client based on unloaders in one or more modules. !!! note @@ -4821,7 +4753,7 @@ def unload_component(client: tanjun.Client) -> None: """ @abc.abstractmethod - def reload_modules(self, *modules: typing.Union[str, pathlib.Path]) -> Self: + def reload_modules(self, *modules: str | pathlib.Path) -> Self: r"""Reload entities in this client based on the loaders in loaded module(s). !!! note @@ -4871,7 +4803,7 @@ def reload_modules(self, *modules: typing.Union[str, pathlib.Path]) -> Self: """ @abc.abstractmethod - async def reload_modules_async(self, *modules: typing.Union[str, pathlib.Path]) -> None: + async def reload_modules_async(self, *modules: str | pathlib.Path) -> None: """Asynchronous variant of [Client.reload_modules][tanjun.abc.Client.reload_modules]. Unlike [Client.reload_modules][tanjun.abc.Client.reload_modules], this @@ -4904,10 +4836,10 @@ def get_type_dependency(self, type_: type[_T], /) -> _T: ... @typing.overload @abc.abstractmethod - def get_type_dependency(self, type_: type[_T], /, *, default: _DefaultT) -> typing.Union[_T, _DefaultT]: ... + def get_type_dependency(self, type_: type[_T], /, *, default: _DefaultT) -> _T | _DefaultT: ... @abc.abstractmethod - def get_type_dependency(self, type_: type[_T], /, *, default: _DefaultT = ...) -> typing.Union[_T, _DefaultT]: + def get_type_dependency(self, type_: type[_T], /, *, default: _DefaultT = ...) -> _T | _DefaultT: """Get the implementation for an injected type. Parameters @@ -4969,7 +4901,7 @@ def set_callback_override(self, callback: alluka.CallbackSig[_T], override: allu """ @abc.abstractmethod - def get_callback_override(self, callback: alluka.CallbackSig[_T], /) -> typing.Optional[alluka.CallbackSig[_T]]: + def get_callback_override(self, callback: alluka.CallbackSig[_T], /) -> alluka.CallbackSig[_T] | None: """Get the override for a specific injected callback. Parameters diff --git a/tanjun/annotations.py b/tanjun/annotations.py index 4e682bd9d..33b51d332 100644 --- a/tanjun/annotations.py +++ b/tanjun/annotations.py @@ -124,7 +124,7 @@ async def message_command( ctx: tanjun.abc.MessageContext, name: Str, value: Str, - enable: typing.Optional[Bool] = None, + enable: Bool | None = None, ) -> None: raise NotImplementedError ``` @@ -248,6 +248,7 @@ async def command( import dataclasses import datetime import enum +import inspect import itertools import operator import typing @@ -261,28 +262,27 @@ async def command( from . import abc as tanjun from . import conversion from . import parsing -from ._internal.vendor import inspect from .commands import message from .commands import slash if typing.TYPE_CHECKING: - from typing_extensions import Self + from typing import Self _T = typing.TypeVar("_T") _OtherT = typing.TypeVar("_OtherT") _ConverterSig = collections.Callable[ - typing_extensions.Concatenate[str, ...], typing.Union[collections.Coroutine[typing.Any, typing.Any, _T], _T] + typing.Concatenate[str, ...], collections.Coroutine[typing.Any, typing.Any, _T] | _T ] - _ChannelTypeIsh = typing.Union[type[hikari.PartialChannel], int] - _ChoiceUnion = typing.Union[int, float, str] + _ChannelTypeIsh = type[hikari.PartialChannel] | int + _ChoiceUnion = int | float | str _ChoiceT = typing.TypeVar("_ChoiceT", int, float, str) - _CommandUnion = typing.Union[slash.SlashCommand[typing.Any], message.MessageCommand[typing.Any]] + _CommandUnion = slash.SlashCommand[typing.Any] | message.MessageCommand[typing.Any] _CommandUnionT = typing.TypeVar("_CommandUnionT", bound=_CommandUnion) _EnumT = typing.TypeVar("_EnumT", bound="enum.Enum") _NumberT = typing.TypeVar("_NumberT", float, int) -_MentionableUnion = typing.Union[hikari.User, hikari.Role] +_MentionableUnion = hikari.User | hikari.Role class _ConfigIdentifier(abc.ABC): @@ -353,7 +353,7 @@ def set_config(self, config: _ArgConfig, /) -> None: commands (unlike [annotations.Member][tanjun.annotations.Member]). """ -Mentionable = typing.Annotated[typing.Union[hikari.User, hikari.Role], _OptionMarker(_MentionableUnion)] +Mentionable = typing.Annotated[hikari.User | hikari.Role, _OptionMarker(_MentionableUnion)] """Type-hint for marking an argument which takes a user or role.""" Role = typing.Annotated[hikari.Role, _OptionMarker(hikari.Role)] @@ -388,20 +388,20 @@ class _Field(_ConfigIdentifier): ) _channel_types: collections.Sequence[_ChannelTypeIsh] - _choices: typing.Optional[collections.Mapping[str, _ChoiceUnion]] + _choices: collections.Mapping[str, _ChoiceUnion] | None _default: typing.Any _description: str _empty_value: typing.Any - _is_greedy: typing.Optional[bool] - _is_positional: typing.Optional[bool] + _is_greedy: bool | None + _is_positional: bool | None _message_names: collections.Sequence[str] - _min_length: typing.Union[int, None] - _max_length: typing.Union[int, None] - _min_value: typing.Union[int, float, None] - _max_value: typing.Union[int, float, None] + _min_length: int | None + _max_length: int | None + _min_value: int | float | None + _max_value: int | float | None _option_type: typing.Any _slash_name: str - _snowflake_converter: typing.Optional[collections.Callable[[str], hikari.Snowflake]] + _snowflake_converter: collections.Callable[[str], hikari.Snowflake] | None _str_converters: collections.Sequence[_ConverterSig[typing.Any]] # TODO: _float_converter, _int_converter @@ -413,20 +413,20 @@ def new( /, *, channel_types: collections.Sequence[_ChannelTypeIsh] = (), - choices: typing.Optional[collections.Mapping[str, _ChoiceUnion]] = None, + choices: collections.Mapping[str, _ChoiceUnion] | None = None, default: typing.Any = tanjun.NO_DEFAULT, description: str = "", empty_value: typing.Any = tanjun.NO_DEFAULT, - greedy: typing.Optional[bool] = None, + greedy: bool | None = None, message_names: collections.Sequence[str] = (), - min_length: typing.Union[int, None] = None, - max_length: typing.Union[int, None] = None, - min_value: typing.Union[int, float, None] = None, - max_value: typing.Union[int, float, None] = None, - positional: typing.Optional[bool] = None, + min_length: int | None = None, + max_length: int | None = None, + min_value: int | float | None = None, + max_value: int | float | None = None, + positional: bool | None = None, slash_name: str = "", - snowflake_converter: typing.Optional[collections.Callable[[str], hikari.Snowflake]] = None, - str_converters: typing.Union[_ConverterSig[typing.Any], collections.Sequence[_ConverterSig[typing.Any]]] = (), + snowflake_converter: collections.Callable[[str], hikari.Snowflake] | None = None, + str_converters: _ConverterSig[typing.Any] | collections.Sequence[_ConverterSig[typing.Any]] = (), ) -> _T: if not isinstance(str_converters, collections.Sequence): str_converters = (str_converters,) @@ -494,8 +494,8 @@ def set_config(self, config: _ArgConfig, /) -> None: def attachment_field( - *, default: typing.Union[_T, tanjun.NoDefault] = tanjun.NO_DEFAULT, description: str = "", slash_name: str = "" -) -> typing.Union[hikari.Attachment, _T]: + *, default: _T | tanjun.NoDefault = tanjun.NO_DEFAULT, description: str = "", slash_name: str = "" +) -> hikari.Attachment | _T: """Mark a parameter as an attachment option using a descriptor. !!! warning @@ -527,14 +527,14 @@ async def command( def bool_field( *, - default: typing.Union[_T, tanjun.NoDefault] = tanjun.NO_DEFAULT, + default: _T | tanjun.NoDefault = tanjun.NO_DEFAULT, description: str = "", - empty_value: typing.Union[_T, tanjun.NoDefault] = tanjun.NO_DEFAULT, - greedy: typing.Optional[bool] = None, + empty_value: _T | tanjun.NoDefault = tanjun.NO_DEFAULT, + greedy: bool | None = None, message_names: collections.Sequence[str] = (), - positional: typing.Optional[bool] = None, + positional: bool | None = None, slash_name: str = "", -) -> typing.Union[bool, _T]: +) -> bool | _T: """Mark a parameter as a bool option using a descriptor. Examples @@ -599,44 +599,44 @@ async def command( def channel_field( *, channel_types: collections.Sequence[_ChannelTypeIsh] = (), - default: typing.Union[_T, tanjun.NoDefault] = tanjun.NO_DEFAULT, + default: _T | tanjun.NoDefault = tanjun.NO_DEFAULT, description: str = "", - empty_value: typing.Union[_T, tanjun.NoDefault] = tanjun.NO_DEFAULT, - greedy: typing.Optional[bool] = None, + empty_value: _T | tanjun.NoDefault = tanjun.NO_DEFAULT, + greedy: bool | None = None, message_names: collections.Sequence[str] = (), or_snowflake: typing.Literal[False] = False, - positional: typing.Optional[bool] = None, + positional: bool | None = None, slash_name: str = "", -) -> typing.Union[hikari.PartialChannel, _T]: ... +) -> hikari.PartialChannel | _T: ... @typing.overload def channel_field( *, channel_types: collections.Sequence[_ChannelTypeIsh] = (), - default: typing.Union[_T, tanjun.NoDefault] = tanjun.NO_DEFAULT, + default: _T | tanjun.NoDefault = tanjun.NO_DEFAULT, description: str = "", - empty_value: typing.Union[_T, tanjun.NoDefault] = tanjun.NO_DEFAULT, - greedy: typing.Optional[bool] = None, + empty_value: _T | tanjun.NoDefault = tanjun.NO_DEFAULT, + greedy: bool | None = None, message_names: collections.Sequence[str] = (), or_snowflake: typing.Literal[True], - positional: typing.Optional[bool] = None, + positional: bool | None = None, slash_name: str = "", -) -> typing.Union[hikari.PartialChannel, hikari.Snowflake, _T]: ... +) -> hikari.PartialChannel | hikari.Snowflake | _T: ... def channel_field( *, channel_types: collections.Sequence[_ChannelTypeIsh] = (), - default: typing.Union[_T, tanjun.NoDefault] = tanjun.NO_DEFAULT, + default: _T | tanjun.NoDefault = tanjun.NO_DEFAULT, description: str = "", - empty_value: typing.Union[_T, tanjun.NoDefault] = tanjun.NO_DEFAULT, - greedy: typing.Optional[bool] = None, + empty_value: _T | tanjun.NoDefault = tanjun.NO_DEFAULT, + greedy: bool | None = None, message_names: collections.Sequence[str] = (), or_snowflake: bool = False, - positional: typing.Optional[bool] = None, + positional: bool | None = None, slash_name: str = "", -) -> typing.Union[hikari.PartialChannel, hikari.Snowflake, _T]: +) -> hikari.PartialChannel | hikari.Snowflake | _T: """Mark a parameter as a channel option using a descriptor. ```py @@ -707,17 +707,17 @@ async def command( def float_field( *, - choices: typing.Optional[collections.Mapping[str, float]] = None, - default: typing.Union[_T, tanjun.NoDefault] = tanjun.NO_DEFAULT, + choices: collections.Mapping[str, float] | None = None, + default: _T | tanjun.NoDefault = tanjun.NO_DEFAULT, description: str = "", - empty_value: typing.Union[_T, tanjun.NoDefault] = tanjun.NO_DEFAULT, - greedy: typing.Optional[bool] = None, + empty_value: _T | tanjun.NoDefault = tanjun.NO_DEFAULT, + greedy: bool | None = None, message_names: collections.Sequence[str] = (), - min_value: typing.Optional[float] = None, - max_value: typing.Optional[float] = None, - positional: typing.Optional[bool] = None, + min_value: float | None = None, + max_value: float | None = None, + positional: bool | None = None, slash_name: str = "", -) -> typing.Union[float, _T]: +) -> float | _T: """Mark a parameter as a float option using a descriptor. ```py @@ -789,17 +789,17 @@ async def command( def int_field( *, - choices: typing.Optional[collections.Mapping[str, int]] = None, - default: typing.Union[_T, tanjun.NoDefault] = tanjun.NO_DEFAULT, + choices: collections.Mapping[str, int] | None = None, + default: _T | tanjun.NoDefault = tanjun.NO_DEFAULT, description: str = "", - empty_value: typing.Union[_T, tanjun.NoDefault] = tanjun.NO_DEFAULT, - greedy: typing.Optional[bool] = None, + empty_value: _T | tanjun.NoDefault = tanjun.NO_DEFAULT, + greedy: bool | None = None, message_names: collections.Sequence[str] = (), - min_value: typing.Optional[int] = None, - max_value: typing.Optional[int] = None, - positional: typing.Optional[bool] = None, + min_value: int | None = None, + max_value: int | None = None, + positional: bool | None = None, slash_name: str = "", -) -> typing.Union[int, _T]: +) -> int | _T: """Mark a parameter as a int option using a descriptor. ```py @@ -872,42 +872,42 @@ async def command( @typing.overload def member_field( *, - default: typing.Union[_T, tanjun.NoDefault] = tanjun.NO_DEFAULT, + default: _T | tanjun.NoDefault = tanjun.NO_DEFAULT, description: str = "", - empty_value: typing.Union[_T, tanjun.NoDefault] = tanjun.NO_DEFAULT, - greedy: typing.Optional[bool] = None, + empty_value: _T | tanjun.NoDefault = tanjun.NO_DEFAULT, + greedy: bool | None = None, message_names: collections.Sequence[str] = (), or_snowflake: typing.Literal[False] = False, - positional: typing.Optional[bool] = None, + positional: bool | None = None, slash_name: str = "", -) -> typing.Union[hikari.Member, _T]: ... +) -> hikari.Member | _T: ... @typing.overload def member_field( *, - default: typing.Union[_T, tanjun.NoDefault] = tanjun.NO_DEFAULT, + default: _T | tanjun.NoDefault = tanjun.NO_DEFAULT, description: str = "", - empty_value: typing.Union[_T, tanjun.NoDefault] = tanjun.NO_DEFAULT, - greedy: typing.Optional[bool] = None, + empty_value: _T | tanjun.NoDefault = tanjun.NO_DEFAULT, + greedy: bool | None = None, message_names: collections.Sequence[str] = (), or_snowflake: typing.Literal[True], - positional: typing.Optional[bool] = None, + positional: bool | None = None, slash_name: str = "", -) -> typing.Union[hikari.Member, hikari.Snowflake, _T]: ... +) -> hikari.Member | hikari.Snowflake | _T: ... def member_field( *, - default: typing.Union[_T, tanjun.NoDefault] = tanjun.NO_DEFAULT, + default: _T | tanjun.NoDefault = tanjun.NO_DEFAULT, description: str = "", - empty_value: typing.Union[_T, tanjun.NoDefault] = tanjun.NO_DEFAULT, - greedy: typing.Optional[bool] = None, + empty_value: _T | tanjun.NoDefault = tanjun.NO_DEFAULT, + greedy: bool | None = None, message_names: collections.Sequence[str] = (), or_snowflake: bool = False, - positional: typing.Optional[bool] = None, + positional: bool | None = None, slash_name: str = "", -) -> typing.Union[hikari.Member, hikari.Snowflake, _T]: +) -> hikari.Member | hikari.Snowflake | _T: """Mark a parameter as a guild member option using a descriptor. ```py @@ -974,42 +974,42 @@ async def command( @typing.overload def mentionable_field( *, - default: typing.Union[_T, tanjun.NoDefault] = tanjun.NO_DEFAULT, + default: _T | tanjun.NoDefault = tanjun.NO_DEFAULT, description: str = "", - empty_value: typing.Union[_T, tanjun.NoDefault] = tanjun.NO_DEFAULT, - greedy: typing.Optional[bool] = None, + empty_value: _T | tanjun.NoDefault = tanjun.NO_DEFAULT, + greedy: bool | None = None, message_names: collections.Sequence[str] = (), or_snowflake: typing.Literal[False] = False, - positional: typing.Optional[bool] = None, + positional: bool | None = None, slash_name: str = "", -) -> typing.Union[hikari.User, hikari.Role, _T]: ... +) -> hikari.User | hikari.Role | _T: ... @typing.overload def mentionable_field( *, - default: typing.Union[_T, tanjun.NoDefault] = tanjun.NO_DEFAULT, + default: _T | tanjun.NoDefault = tanjun.NO_DEFAULT, description: str = "", - empty_value: typing.Union[_T, tanjun.NoDefault] = tanjun.NO_DEFAULT, - greedy: typing.Optional[bool] = None, + empty_value: _T | tanjun.NoDefault = tanjun.NO_DEFAULT, + greedy: bool | None = None, message_names: collections.Sequence[str] = (), or_snowflake: typing.Literal[True], - positional: typing.Optional[bool] = None, + positional: bool | None = None, slash_name: str = "", -) -> typing.Union[hikari.User, hikari.Role, hikari.Snowflake, _T]: ... +) -> hikari.User | hikari.Role | hikari.Snowflake | _T: ... def mentionable_field( *, - default: typing.Union[_T, tanjun.NoDefault] = tanjun.NO_DEFAULT, + default: _T | tanjun.NoDefault = tanjun.NO_DEFAULT, description: str = "", - empty_value: typing.Union[_T, tanjun.NoDefault] = tanjun.NO_DEFAULT, - greedy: typing.Optional[bool] = None, + empty_value: _T | tanjun.NoDefault = tanjun.NO_DEFAULT, + greedy: bool | None = None, message_names: collections.Sequence[str] = (), or_snowflake: bool = False, - positional: typing.Optional[bool] = None, + positional: bool | None = None, slash_name: str = "", -) -> typing.Union[hikari.User, hikari.Role, hikari.Snowflake, _T]: +) -> hikari.User | hikari.Role | hikari.Snowflake | _T: """Mark a parameter as a "mentionable" option using a descriptor. Mentionable options allow both user and roles. @@ -1063,7 +1063,7 @@ async def command( The name to use for this option in slash commands. """ return _Field.new( - _MentionableUnion, + typing.cast("type[hikari.User | hikari.Role | hikari.Snowflake | _T]", _MentionableUnion), default=default, description=description, empty_value=empty_value, @@ -1078,42 +1078,42 @@ async def command( @typing.overload def role_field( *, - default: typing.Union[_T, tanjun.NoDefault] = tanjun.NO_DEFAULT, + default: _T | tanjun.NoDefault = tanjun.NO_DEFAULT, description: str = "", - empty_value: typing.Union[_T, tanjun.NoDefault] = tanjun.NO_DEFAULT, - greedy: typing.Optional[bool] = None, + empty_value: _T | tanjun.NoDefault = tanjun.NO_DEFAULT, + greedy: bool | None = None, message_names: collections.Sequence[str] = (), or_snowflake: typing.Literal[False] = False, - positional: typing.Optional[bool] = None, + positional: bool | None = None, slash_name: str = "", -) -> typing.Union[hikari.Role, _T]: ... +) -> hikari.Role | _T: ... @typing.overload def role_field( *, - default: typing.Union[_T, tanjun.NoDefault] = tanjun.NO_DEFAULT, + default: _T | tanjun.NoDefault = tanjun.NO_DEFAULT, description: str = "", - empty_value: typing.Union[_T, tanjun.NoDefault] = tanjun.NO_DEFAULT, - greedy: typing.Optional[bool] = None, + empty_value: _T | tanjun.NoDefault = tanjun.NO_DEFAULT, + greedy: bool | None = None, message_names: collections.Sequence[str] = (), or_snowflake: typing.Literal[True], - positional: typing.Optional[bool] = None, + positional: bool | None = None, slash_name: str = "", -) -> typing.Union[hikari.Role, hikari.Snowflake, _T]: ... +) -> hikari.Role | hikari.Snowflake | _T: ... def role_field( *, - default: typing.Union[_T, tanjun.NoDefault] = tanjun.NO_DEFAULT, + default: _T | tanjun.NoDefault = tanjun.NO_DEFAULT, description: str = "", - empty_value: typing.Union[_T, tanjun.NoDefault] = tanjun.NO_DEFAULT, - greedy: typing.Optional[bool] = None, + empty_value: _T | tanjun.NoDefault = tanjun.NO_DEFAULT, + greedy: bool | None = None, message_names: collections.Sequence[str] = (), or_snowflake: bool = False, - positional: typing.Optional[bool] = None, + positional: bool | None = None, slash_name: str = "", -) -> typing.Union[hikari.Role, hikari.Snowflake, _T]: +) -> hikari.Role | hikari.Snowflake | _T: """Mark a parameter as a guild role option using a descriptor. ```py @@ -1180,50 +1180,50 @@ async def command( @typing.overload def str_field( *, - choices: typing.Optional[collections.Mapping[str, str]] = None, - default: typing.Union[_T, tanjun.NoDefault] = tanjun.NO_DEFAULT, + choices: collections.Mapping[str, str] | None = None, + default: _T | tanjun.NoDefault = tanjun.NO_DEFAULT, description: str = "", - empty_value: typing.Union[_T, tanjun.NoDefault] = tanjun.NO_DEFAULT, - greedy: typing.Optional[bool] = None, + empty_value: _T | tanjun.NoDefault = tanjun.NO_DEFAULT, + greedy: bool | None = None, message_names: collections.Sequence[str] = (), - min_length: typing.Union[int, None] = None, - max_length: typing.Union[int, None] = None, - positional: typing.Optional[bool] = None, + min_length: int | None = None, + max_length: int | None = None, + positional: bool | None = None, slash_name: str = "", -) -> typing.Union[str, _T]: ... +) -> str | _T: ... @typing.overload def str_field( *, - choices: typing.Optional[collections.Mapping[str, str]] = None, - converters: typing.Union[_ConverterSig[_OtherT], collections.Sequence[_ConverterSig[_OtherT]]], - default: typing.Union[_T, tanjun.NoDefault] = tanjun.NO_DEFAULT, + choices: collections.Mapping[str, str] | None = None, + converters: _ConverterSig[_OtherT] | collections.Sequence[_ConverterSig[_OtherT]], + default: _T | tanjun.NoDefault = tanjun.NO_DEFAULT, description: str = "", - empty_value: typing.Union[_T, tanjun.NoDefault] = tanjun.NO_DEFAULT, - greedy: typing.Optional[bool] = None, + empty_value: _T | tanjun.NoDefault = tanjun.NO_DEFAULT, + greedy: bool | None = None, message_names: collections.Sequence[str] = (), - min_length: typing.Union[int, None] = None, - max_length: typing.Union[int, None] = None, - positional: typing.Optional[bool] = None, + min_length: int | None = None, + max_length: int | None = None, + positional: bool | None = None, slash_name: str = "", -) -> typing.Union[_OtherT, _T]: ... +) -> _OtherT | _T: ... def str_field( *, - choices: typing.Optional[collections.Mapping[str, str]] = None, - converters: typing.Union[_ConverterSig[_OtherT], collections.Sequence[_ConverterSig[_OtherT]]] = (), - default: typing.Union[_T, tanjun.NoDefault] = tanjun.NO_DEFAULT, + choices: collections.Mapping[str, str] | None = None, + converters: _ConverterSig[_OtherT] | collections.Sequence[_ConverterSig[_OtherT]] = (), + default: _T | tanjun.NoDefault = tanjun.NO_DEFAULT, description: str = "", - empty_value: typing.Union[_T, tanjun.NoDefault] = tanjun.NO_DEFAULT, - greedy: typing.Optional[bool] = None, + empty_value: _T | tanjun.NoDefault = tanjun.NO_DEFAULT, + greedy: bool | None = None, message_names: collections.Sequence[str] = (), - min_length: typing.Union[int, None] = None, - max_length: typing.Union[int, None] = None, - positional: typing.Optional[bool] = None, + min_length: int | None = None, + max_length: int | None = None, + positional: bool | None = None, slash_name: str = "", -) -> typing.Union[str, _T, _OtherT]: +) -> str | _T | _OtherT: """Mark a parameter as a string option using a descriptor. Examples @@ -1307,42 +1307,42 @@ async def command( @typing.overload def user_field( *, - default: typing.Union[_T, tanjun.NoDefault] = tanjun.NO_DEFAULT, + default: _T | tanjun.NoDefault = tanjun.NO_DEFAULT, description: str = "", - empty_value: typing.Union[_T, tanjun.NoDefault] = tanjun.NO_DEFAULT, - greedy: typing.Optional[bool] = None, + empty_value: _T | tanjun.NoDefault = tanjun.NO_DEFAULT, + greedy: bool | None = None, message_names: collections.Sequence[str] = (), or_snowflake: typing.Literal[False] = False, - positional: typing.Optional[bool] = None, + positional: bool | None = None, slash_name: str = "", -) -> typing.Union[hikari.User, _T]: ... +) -> hikari.User | _T: ... @typing.overload def user_field( *, - default: typing.Union[_T, tanjun.NoDefault] = tanjun.NO_DEFAULT, + default: _T | tanjun.NoDefault = tanjun.NO_DEFAULT, description: str = "", - empty_value: typing.Union[_T, tanjun.NoDefault] = tanjun.NO_DEFAULT, - greedy: typing.Optional[bool] = None, + empty_value: _T | tanjun.NoDefault = tanjun.NO_DEFAULT, + greedy: bool | None = None, message_names: collections.Sequence[str] = (), or_snowflake: typing.Literal[True], - positional: typing.Optional[bool] = None, + positional: bool | None = None, slash_name: str = "", -) -> typing.Union[hikari.User, hikari.Snowflake, _T]: ... +) -> hikari.User | hikari.Snowflake | _T: ... def user_field( *, - default: typing.Union[_T, tanjun.NoDefault] = tanjun.NO_DEFAULT, + default: _T | tanjun.NoDefault = tanjun.NO_DEFAULT, description: str = "", - empty_value: typing.Union[_T, tanjun.NoDefault] = tanjun.NO_DEFAULT, - greedy: typing.Optional[bool] = None, + empty_value: _T | tanjun.NoDefault = tanjun.NO_DEFAULT, + greedy: bool | None = None, message_names: collections.Sequence[str] = (), or_snowflake: bool = False, - positional: typing.Optional[bool] = None, + positional: bool | None = None, slash_name: str = "", -) -> typing.Union[hikari.User, hikari.Snowflake, _T]: +) -> hikari.User | hikari.Snowflake | _T: """Mark a parameter as a user option using a descriptor. Examples @@ -1494,11 +1494,11 @@ async def command( def __init__( self, - mapping: typing.Union[ - collections.Mapping[str, _ChoiceT], - collections.Sequence[tuple[str, _ChoiceT]], - collections.Sequence[_ChoiceT], - ] = (), + mapping: ( + collections.Mapping[str, _ChoiceT] + | collections.Sequence[tuple[str, _ChoiceT]] + | collections.Sequence[_ChoiceT] + ) = (), /, **kwargs: _ChoiceT, ) -> None: @@ -1531,7 +1531,7 @@ def set_config(self, config: _ArgConfig, /) -> None: class _ConvertedMeta(abc.ABCMeta): @typing_extensions.deprecated("Pass Converted(...) to Annotated") - def __getitem__(cls, converters: typing.Union[_ConverterSig[_T], tuple[_ConverterSig[_T]]], /) -> type[_T]: + def __getitem__(cls, converters: _ConverterSig[_T] | tuple[_ConverterSig[_T]], /) -> type[_T]: if not isinstance(converters, tuple): converters = (converters,) @@ -1561,12 +1561,12 @@ def __init__(self, converter: _ConverterSig[typing.Any], /, *other_converters: _ Parameters ---------- - converter : collections.abc.Callable[[str, ...], collections.Coroutine[Any, Any, Any] | Any] + converter : collections.abc.Callable[[str, ...], collections.abc.Coroutine[Any, Any, Any] | Any] The first converter this argument should use to handle values passed to it during parsing. Only the first converter to pass will be used. - *other_converters : collections.abc.Callable[[str, ...], collections.Coroutine[Any, Any, Any] | Any] + *other_converters : collections.abc.Callable[[str, ...], collections.abc.Coroutine[Any, Any, Any] | Any] Other first converter(s) this argument should use to handle values passed to it during parsing. @@ -1603,7 +1603,7 @@ def _annotated(type_: type[_T], config: _ConfigIdentifier, /) -> type[_T]: class _DefaultMeta(abc.ABCMeta): @typing_extensions.deprecated("Pass Default(...) to Annotated") - def __getitem__(cls, value: typing.Union[type[_T], tuple[type[_T], _T]], /) -> type[_T]: + def __getitem__(cls, value: type[_T] | tuple[type[_T], _T], /) -> type[_T]: if isinstance(value, tuple): type_ = value[0] return _annotated(type_, Default(value[1])) @@ -1692,7 +1692,7 @@ async def command( @typing.overload def __init__( - self, *, aliases: typing.Optional[collections.Sequence[str]] = None, empty_value: typing.Any = tanjun.NO_DEFAULT + self, *, aliases: collections.Sequence[str] | None = None, empty_value: typing.Any = tanjun.NO_DEFAULT ) -> None: ... @typing_extensions.deprecated("Use annotations.Default instead of the default arg") @@ -1700,7 +1700,7 @@ def __init__( def __init__( self, *, - aliases: typing.Optional[collections.Sequence[str]] = None, + aliases: collections.Sequence[str] | None = None, default: typing.Any = tanjun.NO_DEFAULT, empty_value: typing.Any = tanjun.NO_DEFAULT, ) -> None: ... @@ -1708,7 +1708,7 @@ def __init__( def __init__( self, *, - aliases: typing.Optional[collections.Sequence[str]] = None, + aliases: collections.Sequence[str] | None = None, default: typing.Any = tanjun.NO_DEFAULT, empty_value: typing.Any = tanjun.NO_DEFAULT, ) -> None: @@ -1738,7 +1738,7 @@ def __init__( self._empty_value = empty_value @property - def aliases(self) -> typing.Optional[collections.Sequence[str]]: + def aliases(self) -> collections.Sequence[str] | None: """The aliases set for this flag. These do not override the flag's name. @@ -1843,7 +1843,7 @@ def set_config(self, config: _ArgConfig, /) -> None: class _LengthMeta(abc.ABCMeta): @typing_extensions.deprecated("Pass Length(...) to Annotated") - def __getitem__(cls, value: typing.Union[int, tuple[int, int]], /) -> type[str]: + def __getitem__(cls, value: int | tuple[int, int], /) -> type[str]: if isinstance(value, int): obj = Length(value) @@ -1898,7 +1898,7 @@ def __init__(self, max_length: int, /) -> None: ... @typing.overload def __init__(self, min_length: int, max_length: int, /) -> None: ... - def __init__(self, min_or_max_length: int, max_length: typing.Optional[int] = None, /) -> None: + def __init__(self, min_or_max_length: int, max_length: int | None = None, /) -> None: """Initialise a length constraint. Parameters @@ -1966,7 +1966,7 @@ async def command( __slots__ = ("_value",) - def __init__(self, value: typing.Union[int, float], /) -> None: + def __init__(self, value: int | float, /) -> None: """Create an argument maximum value. Parameters @@ -1977,7 +1977,7 @@ def __init__(self, value: typing.Union[int, float], /) -> None: self._value = value @property - def value(self) -> typing.Union[int, float]: + def value(self) -> int | float: """The maximum allowed value.""" return self._value @@ -2013,7 +2013,7 @@ async def command( __slots__ = ("_value",) - def __init__(self, value: typing.Union[int, float], /) -> None: + def __init__(self, value: int | float, /) -> None: """Create an argument minimum value. Parameters @@ -2024,7 +2024,7 @@ def __init__(self, value: typing.Union[int, float], /) -> None: self._value = value @property - def value(self) -> typing.Union[int, float]: + def value(self) -> int | float: """The minimum allowed value.""" return self._value @@ -2051,14 +2051,7 @@ async def command( __slots__ = ("_message_name", "_slash_name") - def __init__( - self, - both: typing.Optional[str] = None, - /, - *, - message: typing.Optional[str] = None, - slash: typing.Optional[str] = None, - ) -> None: + def __init__(self, both: str | None = None, /, *, message: str | None = None, slash: str | None = None) -> None: """Create an argument name override. Parameters @@ -2087,12 +2080,12 @@ def __init__( self._slash_name = slash or both @property - def message_name(self) -> typing.Optional[str]: + def message_name(self) -> str | None: """The name to use for this option in message commands.""" return self._message_name @property - def slash_name(self) -> typing.Optional[str]: + def slash_name(self) -> str | None: """The name to use for this option in slash commands.""" return self._slash_name @@ -2151,7 +2144,7 @@ async def command( __slots__ = ("_max_value", "_min_value") - def __init__(self, min_value: typing.Union[int, float], max_value: typing.Union[int, Float], /) -> None: + def __init__(self, min_value: int | float, max_value: int | Float, /) -> None: """Create an argument range limit. Parameters @@ -2165,12 +2158,12 @@ def __init__(self, min_value: typing.Union[int, float], max_value: typing.Union[ self._min_value = min_value @property - def max_value(self) -> typing.Union[int, float]: + def max_value(self) -> int | float: """The maximum allowed value for this argument.""" return self._max_value @property - def min_value(self) -> typing.Union[int, float]: + def min_value(self) -> int | float: """The minimum allowed value for this argument.""" return self._min_value @@ -2190,7 +2183,7 @@ def set_config(self, config: _ArgConfig, /) -> None: class _SnowflakeOrMeta(abc.ABCMeta): @typing_extensions.deprecated("Pass SnowflakeOr(...) to Annotated") - def __getitem__(cls, type_: type[_T], /) -> type[typing.Union[hikari.Snowflake, _T]]: + def __getitem__(cls, type_: type[_T], /) -> type[hikari.Snowflake | _T]: for entry in _snoop_annotation_args(type_): if not isinstance(entry, _OptionMarker): continue @@ -2208,7 +2201,7 @@ def __getitem__(cls, type_: type[_T], /) -> type[typing.Union[hikari.Snowflake, else: descriptor = SnowflakeOr() - return _annotated(typing.Union[hikari.Snowflake, type_], descriptor) + return _annotated(typing.cast("type[hikari.Snowflake | type_]", hikari.Snowflake | type_), descriptor) class SnowflakeOr(_ConfigIdentifier, metaclass=_SnowflakeOrMeta): @@ -2265,7 +2258,7 @@ def set_config(self, config: _ArgConfig, /) -> None: class _TheseChannelsMeta(abc.ABCMeta): @typing_extensions.deprecated("Pass TheseChannels(...) to Annotated") def __getitem__( - cls, value: typing.Union[_ChannelTypeIsh, collections.Collection[_ChannelTypeIsh]], / + cls, value: _ChannelTypeIsh | collections.Collection[_ChannelTypeIsh], / ) -> type[hikari.PartialChannel]: if not isinstance(value, collections.Collection): value = (value,) @@ -2299,7 +2292,7 @@ def set_config(self, config: _ArgConfig, /) -> None: config.channel_types = self._channel_types -def _ensure_value(name: str, type_: type[_T], value: typing.Optional[typing.Any], /) -> typing.Optional[_T]: +def _ensure_value(name: str, type_: type[_T], value: typing.Any | None, /) -> _T | None: if value is None or isinstance(value, type_): return value @@ -2309,8 +2302,8 @@ def _ensure_value(name: str, type_: type[_T], value: typing.Optional[typing.Any] def _ensure_values( - name: str, type_: type[_T], mapping: typing.Optional[collections.Mapping[str, typing.Any]], / -) -> typing.Optional[collections.Mapping[str, _T]]: + name: str, type_: type[_T], mapping: collections.Mapping[str, typing.Any] | None, / +) -> collections.Mapping[str, _T] | None: if not mapping: return None @@ -2370,29 +2363,29 @@ class _ArgConfig: "str_converters", ) - def __init__(self, key: str, default: typing.Any, /, *, description: typing.Optional[str]) -> None: + def __init__(self, key: str, default: typing.Any, /, *, description: str | None) -> None: self.channel_types: collections.Sequence[_ChannelTypeIsh] = () - self.choices: typing.Optional[collections.Mapping[str, _ChoiceUnion]] = None + self.choices: collections.Mapping[str, _ChoiceUnion] | None = None self.default: typing.Any = default - self.description: typing.Optional[str] = description + self.description: str | None = description self.empty_value: typing.Any = tanjun.NO_DEFAULT - self.float_converter: typing.Optional[collections.Callable[[float], typing.Any]] = None + self.float_converter: collections.Callable[[float], typing.Any] | None = None self.has_natural_default: bool = default is tanjun.NO_PASS - self.int_converter: typing.Optional[collections.Callable[[int], typing.Any]] = None + self.int_converter: collections.Callable[[int], typing.Any] | None = None # The float and int converters are just for Choices[Enum]. - self.is_greedy: typing.Optional[bool] = None - self.is_positional: typing.Optional[bool] = None + self.is_greedy: bool | None = None + self.is_positional: bool | None = None self.key: str = key self.main_message_name: str = "--" + key.replace("_", "-") - self.min_length: typing.Optional[int] = None - self.max_length: typing.Optional[int] = None - self.min_value: typing.Union[float, int, None] = None - self.max_value: typing.Union[float, int, None] = None + self.min_length: int | None = None + self.max_length: int | None = None + self.min_value: float | int | None = None + self.max_value: float | int | None = None self.message_names: collections.Sequence[str] = [self.main_message_name] - self.option_type: typing.Optional[typing.Any] = None - self.range_or_slice: typing.Union[range, slice, None] = None + self.option_type: typing.Any | None = None + self.range_or_slice: range | slice | None = None self.slash_name: str = key - self.snowflake_converter: typing.Optional[collections.Callable[[str], hikari.Snowflake]] = None + self.snowflake_converter: collections.Callable[[str], hikari.Snowflake] | None = None self.str_converters: collections.Sequence[_ConverterSig[typing.Any]] = () def set_option_type(self, option_type: typing.Any, /) -> None: @@ -2571,28 +2564,28 @@ def add_to_slash_cmds(self, commands: collections.Sequence[slash.SlashCommand[ty SLASH_OPTION_ADDER[hikari.InteractionMember] = SLASH_OPTION_ADDER[hikari.Member] -_WRAPPER_TYPES = {typing_extensions.Required, typing_extensions.NotRequired} +_WRAPPER_TYPES = {typing.Required, typing.NotRequired} def _snoop_annotation_args(type_: typing.Any, /) -> collections.Iterator[typing.Any]: - origin = typing_extensions.get_origin(type_) + origin = typing.get_origin(type_) if origin is typing.Annotated: - args = typing_extensions.get_args(type_) + args = typing.get_args(type_) yield from _snoop_annotation_args(args[0]) yield from args[1:] elif origin in _internal.UnionTypes: - yield from itertools.chain.from_iterable(map(_snoop_annotation_args, typing_extensions.get_args(type_))) + yield from itertools.chain.from_iterable(map(_snoop_annotation_args, typing.get_args(type_))) elif origin in _WRAPPER_TYPES: - yield from _snoop_annotation_args(typing_extensions.get_args(type_)[0]) + yield from _snoop_annotation_args(typing.get_args(type_)[0]) def parse_annotated_args( - command: typing.Union[slash.SlashCommand[typing.Any], message.MessageCommand[typing.Any]], + command: slash.SlashCommand[typing.Any] | message.MessageCommand[typing.Any], /, *, - descriptions: typing.Optional[collections.Mapping[str, str]] = None, + descriptions: collections.Mapping[str, str] | None = None, follow_wrapped: bool = False, ) -> None: """Set a command's arguments based on its signature. @@ -2659,14 +2652,14 @@ def parse_annotated_args( ) continue - if typing_extensions.get_origin(parameter.annotation) is not typing_extensions.Unpack: + if typing.get_origin(parameter.annotation) is not typing.Unpack: continue - typed_dict = typing_extensions.get_args(parameter.annotation)[0] - if not typing_extensions.is_typeddict(typed_dict): + typed_dict = typing.get_args(parameter.annotation)[0] + if not typing.is_typeddict(typed_dict): continue - for name, annotation in typing_extensions.get_type_hints(typed_dict, include_extras=True).items(): + for name, annotation in typing.get_type_hints(typed_dict, include_extras=True).items(): default = tanjun.NO_PASS if name in typed_dict.__optional_keys__ else tanjun.NO_DEFAULT ( _ArgConfig(name, default, description=descriptions.get(name)) @@ -2688,8 +2681,8 @@ def with_annotated_args(*, follow_wrapped: bool = False) -> collections.Callable def with_annotated_args( - command: typing.Optional[_CommandUnionT] = None, /, *, follow_wrapped: bool = False -) -> typing.Union[_CommandUnionT, collections.Callable[[_CommandUnionT], _CommandUnionT]]: + command: _CommandUnionT | None = None, /, *, follow_wrapped: bool = False +) -> _CommandUnionT | collections.Callable[[_CommandUnionT], _CommandUnionT]: r"""Set a command's arguments based on its signature. For more information on how this works see [tanjun.annotations][]. diff --git a/tanjun/checks.py b/tanjun/checks.py index a18961bb8..a0c23e872 100644 --- a/tanjun/checks.py +++ b/tanjun/checks.py @@ -74,12 +74,12 @@ class _AnyCallback(typing.Protocol[_ContextT_contra]): async def __call__( - self, ctx: _ContextT_contra, /, *, localiser: typing.Optional[dependencies.AbstractLocaliser] = None + self, ctx: _ContextT_contra, /, *, localiser: dependencies.AbstractLocaliser | None = None ) -> bool: raise NotImplementedError _CommandT = typing.TypeVar("_CommandT", bound=tanjun.ExecutableCommand[typing.Any]) - _CallbackReturnT = typing.Union[_CommandT, collections.Callable[[_CommandT], _CommandT]] + _CallbackReturnT = _CommandT | collections.Callable[[_CommandT], _CommandT] _MenuCommandT = typing.TypeVar("_MenuCommandT", bound=tanjun.MenuCommand[typing.Any, typing.Any]) _MessageCommandT = typing.TypeVar("_MessageCommandT", bound=tanjun.MessageCommand[typing.Any]) _SlashCommandT = typing.TypeVar("_SlashCommandT", bound=tanjun.BaseSlashCommand) @@ -93,8 +93,8 @@ def _add_to_command(command: _CommandT, check: tanjun.AnyCheckSig, follow_wrappe def _optional_kwargs( - command: typing.Optional[_CommandT], check: tanjun.AnyCheckSig, follow_wrapped: bool -) -> typing.Union[_CommandT, collections.Callable[[_CommandT], _CommandT]]: + command: _CommandT | None, check: tanjun.AnyCheckSig, follow_wrapped: bool +) -> _CommandT | collections.Callable[[_CommandT], _CommandT]: if command: return _add_to_command(command, check, follow_wrapped) @@ -106,12 +106,12 @@ class _Check: def __init__( self, - error: typing.Optional[collections.Callable[..., Exception]], - error_message: typing.Union[str, collections.Mapping[str, str], None], + error: collections.Callable[..., Exception] | None, + error_message: str | collections.Mapping[str, str] | None, halt_execution: bool, /, *, - id_name: typing.Optional[str] = None, + id_name: str | None = None, ) -> None: self._error = error self._error_message = localisation.MaybeLocalised("error_message", error_message) if error_message else None @@ -122,7 +122,7 @@ def _handle_result( self, ctx: tanjun.Context, result: bool, - localiser: typing.Optional[dependencies.AbstractLocaliser] = None, + localiser: dependencies.AbstractLocaliser | None = None, /, *args: typing.Any, ) -> bool: @@ -149,8 +149,8 @@ class OwnerCheck(_Check): def __init__( self, *, - error: typing.Optional[collections.Callable[[], Exception]] = None, - error_message: typing.Union[str, collections.Mapping[str, str], None] = "Only bot owners can use this command", + error: collections.Callable[[], Exception] | None = None, + error_message: str | collections.Mapping[str, str] | None = "Only bot owners can use this command", halt_execution: bool = False, ) -> None: """Initialise an owner check. @@ -183,7 +183,7 @@ async def __call__( /, dependency: alluka.Injected[dependencies.AbstractOwners], *, - localiser: alluka.Injected[typing.Optional[dependencies.AbstractLocaliser]] = None, + localiser: alluka.Injected[dependencies.AbstractLocaliser | None] = None, ) -> bool: return self._handle_result(ctx, await dependency.check_ownership(ctx.client, ctx.author), localiser) @@ -206,10 +206,8 @@ class NsfwCheck(_Check): def __init__( self, *, - error: typing.Optional[collections.Callable[[], Exception]] = None, - error_message: typing.Union[ - str, collections.Mapping[str, str], None - ] = "Command can only be used in NSFW channels", + error: collections.Callable[[], Exception] | None = None, + error_message: str | collections.Mapping[str, str] | None = "Command can only be used in NSFW channels", halt_execution: bool = False, ) -> None: """Initialise a NSFW check. @@ -237,11 +235,7 @@ def __init__( super().__init__(error, error_message, halt_execution) async def __call__( - self, - ctx: tanjun.Context, - /, - *, - localiser: alluka.Injected[typing.Optional[dependencies.AbstractLocaliser]] = None, + self, ctx: tanjun.Context, /, *, localiser: alluka.Injected[dependencies.AbstractLocaliser | None] = None ) -> bool: return self._handle_result(ctx, await _get_is_nsfw(ctx, dm_default=True), localiser) @@ -257,10 +251,8 @@ class SfwCheck(_Check): def __init__( self, *, - error: typing.Optional[collections.Callable[[], Exception]] = None, - error_message: typing.Union[ - str, collections.Mapping[str, str], None - ] = "Command can only be used in SFW channels", + error: collections.Callable[[], Exception] | None = None, + error_message: str | collections.Mapping[str, str] | None = "Command can only be used in SFW channels", halt_execution: bool = False, ) -> None: """Initialise a SFW check. @@ -288,11 +280,7 @@ def __init__( super().__init__(error, error_message, halt_execution) async def __call__( - self, - ctx: tanjun.Context, - /, - *, - localiser: alluka.Injected[typing.Optional[dependencies.AbstractLocaliser]] = None, + self, ctx: tanjun.Context, /, *, localiser: alluka.Injected[dependencies.AbstractLocaliser | None] = None ) -> bool: return self._handle_result(ctx, not await _get_is_nsfw(ctx, dm_default=False), localiser) @@ -308,8 +296,8 @@ class DmCheck(_Check): def __init__( self, *, - error: typing.Optional[collections.Callable[[], Exception]] = None, - error_message: typing.Union[str, collections.Mapping[str, str], None] = "Command can only be used in DMs", + error: collections.Callable[[], Exception] | None = None, + error_message: str | collections.Mapping[str, str] | None = "Command can only be used in DMs", halt_execution: bool = False, ) -> None: """Initialise a DM check. @@ -337,11 +325,7 @@ def __init__( super().__init__(error, error_message, halt_execution) def __call__( - self, - ctx: tanjun.Context, - /, - *, - localiser: alluka.Injected[typing.Optional[dependencies.AbstractLocaliser]] = None, + self, ctx: tanjun.Context, /, *, localiser: alluka.Injected[dependencies.AbstractLocaliser | None] = None ) -> bool: return self._handle_result(ctx, ctx.guild_id is None, localiser) @@ -357,10 +341,8 @@ class GuildCheck(_Check): def __init__( self, *, - error: typing.Optional[collections.Callable[[], Exception]] = None, - error_message: typing.Union[ - str, collections.Mapping[str, str], None - ] = "Command can only be used in guild channels", + error: collections.Callable[[], Exception] | None = None, + error_message: str | collections.Mapping[str, str] | None = "Command can only be used in guild channels", halt_execution: bool = False, ) -> None: """Initialise a guild check. @@ -388,11 +370,7 @@ def __init__( super().__init__(error, error_message, halt_execution) def __call__( - self, - ctx: tanjun.Context, - /, - *, - localiser: alluka.Injected[typing.Optional[dependencies.AbstractLocaliser]] = None, + self, ctx: tanjun.Context, /, *, localiser: alluka.Injected[dependencies.AbstractLocaliser | None] = None ) -> bool: return self._handle_result(ctx, ctx.guild_id is not None, localiser) @@ -410,13 +388,13 @@ class AuthorPermissionCheck(_Check): def __init__( self, - permissions: typing.Union[hikari.Permissions, int], + permissions: hikari.Permissions | int, /, *, - error: typing.Optional[collections.Callable[[hikari.Permissions], Exception]] = None, - error_message: typing.Union[ - str, collections.Mapping[str, str], None - ] = "You don't have the permissions required to use this command", + error: collections.Callable[[hikari.Permissions], Exception] | None = None, + error_message: ( + str | collections.Mapping[str, str] | None + ) = "You don't have the permissions required to use this command", halt_execution: bool = False, ) -> None: """Initialise an author permission check. @@ -451,11 +429,7 @@ def __init__( self._permissions = permissions async def __call__( - self, - ctx: tanjun.Context, - /, - *, - localiser: alluka.Injected[typing.Optional[dependencies.AbstractLocaliser]] = None, + self, ctx: tanjun.Context, /, *, localiser: alluka.Injected[dependencies.AbstractLocaliser | None] = None ) -> bool: if not ctx.member: # If there's no member when this is within a guild then it's likely @@ -479,7 +453,7 @@ async def __call__( return self._handle_result(ctx, missing_perms is hikari.Permissions.NONE, localiser, missing_perms) -_MemberCacheT = typing.Optional[dependencies.SfGuildBound[hikari.Member]] +_MemberCacheT = None | dependencies.SfGuildBound[hikari.Member] class OwnPermissionCheck(_Check): @@ -495,13 +469,13 @@ class OwnPermissionCheck(_Check): def __init__( self, - permissions: typing.Union[hikari.Permissions, int], + permissions: hikari.Permissions | int, /, *, - error: typing.Optional[collections.Callable[[hikari.Permissions], Exception]] = None, - error_message: typing.Union[ - str, collections.Mapping[str, str], None - ] = "Bot doesn't have the permissions required to run this command", + error: collections.Callable[[hikari.Permissions], Exception] | None = None, + error_message: ( + str | collections.Mapping[str, str] | None + ) = "Bot doesn't have the permissions required to run this command", halt_execution: bool = False, ) -> None: """Initialise a own permission check. @@ -540,7 +514,7 @@ async def __call__( ctx: tanjun.Context, /, *, - localiser: alluka.Injected[typing.Optional[dependencies.AbstractLocaliser]] = None, + localiser: alluka.Injected[dependencies.AbstractLocaliser | None] = None, my_user: hikari.OwnUser = dependencies.inject_lc(hikari.OwnUser), member_cache: alluka.Injected[_MemberCacheT] = None, ) -> bool: @@ -570,19 +544,19 @@ def with_dm_check(command: _CommandT, /) -> _CommandT: ... @typing.overload def with_dm_check( *, - error: typing.Optional[collections.Callable[[], Exception]] = None, - error_message: typing.Union[str, collections.Mapping[str, str], None] = "Command can only be used in DMs", + error: collections.Callable[[], Exception] | None = None, + error_message: str | collections.Mapping[str, str] | None = "Command can only be used in DMs", follow_wrapped: bool = False, halt_execution: bool = False, ) -> collections.Callable[[_CommandT], _CommandT]: ... def with_dm_check( - command: typing.Optional[_CommandT] = None, + command: _CommandT | None = None, /, *, - error: typing.Optional[collections.Callable[[], Exception]] = None, - error_message: typing.Union[str, collections.Mapping[str, str], None] = "Command can only be used in DMs", + error: collections.Callable[[], Exception] | None = None, + error_message: str | collections.Mapping[str, str] | None = "Command can only be used in DMs", follow_wrapped: bool = False, halt_execution: bool = False, ) -> _CallbackReturnT[_CommandT]: @@ -630,23 +604,19 @@ def with_guild_check(command: _CommandT, /) -> _CommandT: ... @typing.overload def with_guild_check( *, - error: typing.Optional[collections.Callable[[], Exception]] = None, - error_message: typing.Union[ - str, collections.Mapping[str, str], None - ] = "Command can only be used in guild channels", + error: collections.Callable[[], Exception] | None = None, + error_message: str | collections.Mapping[str, str] | None = "Command can only be used in guild channels", follow_wrapped: bool = False, halt_execution: bool = False, ) -> collections.Callable[[_CommandT], _CommandT]: ... def with_guild_check( - command: typing.Optional[_CommandT] = None, + command: _CommandT | None = None, /, *, - error: typing.Optional[collections.Callable[[], Exception]] = None, - error_message: typing.Union[ - str, collections.Mapping[str, str], None - ] = "Command can only be used in guild channels", + error: collections.Callable[[], Exception] | None = None, + error_message: str | collections.Mapping[str, str] | None = "Command can only be used in guild channels", follow_wrapped: bool = False, halt_execution: bool = False, ) -> _CallbackReturnT[_CommandT]: @@ -694,19 +664,19 @@ def with_nsfw_check(command: _CommandT, /) -> _CommandT: ... @typing.overload def with_nsfw_check( *, - error: typing.Optional[collections.Callable[[], Exception]] = None, - error_message: typing.Union[str, collections.Mapping[str, str], None] = "Command can only be used in NSFW channels", + error: collections.Callable[[], Exception] | None = None, + error_message: str | collections.Mapping[str, str] | None = "Command can only be used in NSFW channels", follow_wrapped: bool = False, halt_execution: bool = False, ) -> collections.Callable[[_CommandT], _CommandT]: ... def with_nsfw_check( - command: typing.Optional[_CommandT] = None, + command: _CommandT | None = None, /, *, - error: typing.Optional[collections.Callable[[], Exception]] = None, - error_message: typing.Union[str, collections.Mapping[str, str], None] = "Command can only be used in NSFW channels", + error: collections.Callable[[], Exception] | None = None, + error_message: str | collections.Mapping[str, str] | None = "Command can only be used in NSFW channels", follow_wrapped: bool = False, halt_execution: bool = False, ) -> _CallbackReturnT[_CommandT]: @@ -754,19 +724,19 @@ def with_sfw_check(command: _CommandT, /) -> _CommandT: ... @typing.overload def with_sfw_check( *, - error: typing.Optional[collections.Callable[[], Exception]] = None, - error_message: typing.Union[str, collections.Mapping[str, str], None] = "Command can only be used in SFW channels", + error: collections.Callable[[], Exception] | None = None, + error_message: str | collections.Mapping[str, str] | None = "Command can only be used in SFW channels", follow_wrapped: bool = False, halt_execution: bool = False, ) -> collections.Callable[[_CommandT], _CommandT]: ... def with_sfw_check( - command: typing.Optional[_CommandT] = None, + command: _CommandT | None = None, /, *, - error: typing.Optional[collections.Callable[[], Exception]] = None, - error_message: typing.Union[str, collections.Mapping[str, str], None] = "Command can only be used in SFW channels", + error: collections.Callable[[], Exception] | None = None, + error_message: str | collections.Mapping[str, str] | None = "Command can only be used in SFW channels", follow_wrapped: bool = False, halt_execution: bool = False, ) -> _CallbackReturnT[_CommandT]: @@ -814,19 +784,19 @@ def with_owner_check(command: _CommandT, /) -> _CommandT: ... @typing.overload def with_owner_check( *, - error: typing.Optional[collections.Callable[[], Exception]] = None, - error_message: typing.Union[str, collections.Mapping[str, str], None] = "Only bot owners can use this command", + error: collections.Callable[[], Exception] | None = None, + error_message: str | collections.Mapping[str, str] | None = "Only bot owners can use this command", follow_wrapped: bool = False, halt_execution: bool = False, ) -> collections.Callable[[_CommandT], _CommandT]: ... def with_owner_check( - command: typing.Optional[_CommandT] = None, + command: _CommandT | None = None, /, *, - error: typing.Optional[collections.Callable[[], Exception]] = None, - error_message: typing.Union[str, collections.Mapping[str, str], None] = "Only bot owners can use this command", + error: collections.Callable[[], Exception] | None = None, + error_message: str | collections.Mapping[str, str] | None = "Only bot owners can use this command", follow_wrapped: bool = False, halt_execution: bool = False, ) -> _CallbackReturnT[_CommandT]: @@ -868,12 +838,12 @@ def with_owner_check( def with_author_permission_check( - permissions: typing.Union[hikari.Permissions, int], + permissions: hikari.Permissions | int, *, - error: typing.Optional[collections.Callable[[hikari.Permissions], Exception]] = None, - error_message: typing.Union[ - str, collections.Mapping[str, str], None - ] = "You don't have the permissions required to use this command", + error: collections.Callable[[hikari.Permissions], Exception] | None = None, + error_message: ( + str | collections.Mapping[str, str] | None + ) = "You don't have the permissions required to use this command", follow_wrapped: bool = False, halt_execution: bool = False, ) -> collections.Callable[[_CommandT], _CommandT]: @@ -925,12 +895,12 @@ def with_author_permission_check( def with_own_permission_check( - permissions: typing.Union[hikari.Permissions, int], + permissions: hikari.Permissions | int, *, - error: typing.Optional[collections.Callable[[hikari.Permissions], Exception]] = None, - error_message: typing.Union[ - str, collections.Mapping[str, str], None - ] = "Bot doesn't have the permissions required to run this command", + error: collections.Callable[[hikari.Permissions], Exception] | None = None, + error_message: ( + str | collections.Mapping[str, str] | None + ) = "Bot doesn't have the permissions required to run this command", follow_wrapped: bool = False, halt_execution: bool = False, ) -> collections.Callable[[_CommandT], _CommandT]: @@ -1007,12 +977,12 @@ def with_check( def with_check( check: tanjun.CheckSig[typing.Any], /, *, follow_wrapped: bool = False -) -> typing.Union[ - collections.Callable[[_CommandT], _CommandT], - collections.Callable[[_MenuCommandT], _MenuCommandT], - collections.Callable[[_MessageCommandT], _MessageCommandT], - collections.Callable[[_SlashCommandT], _SlashCommandT], -]: +) -> ( + collections.Callable[[_CommandT], _CommandT] + | collections.Callable[[_MenuCommandT], _MenuCommandT] + | collections.Callable[[_MessageCommandT], _MessageCommandT] + | collections.Callable[[_SlashCommandT], _SlashCommandT] +): """Add a generic check to a command. Parameters @@ -1062,7 +1032,7 @@ def all_checks( Returns ------- - collections.abc.Callable[[tanjun.abc.Context], collections.abc.Coroutine[typing.Any, typing.Any, bool]] + collections.abc.Callable[[tanjun.abc.Context], collections.Coroutine[typing.Any, typing.Any, bool]] A check which will pass if all of the provided check callbacks pass. """ return _AllChecks[_ContextT]([check, *checks]) @@ -1103,12 +1073,12 @@ def with_all_checks( def with_all_checks( check: tanjun.CheckSig[typing.Any], /, *checks: tanjun.CheckSig[typing.Any], follow_wrapped: bool = False -) -> typing.Union[ - collections.Callable[[_CommandT], _CommandT], - collections.Callable[[_MenuCommandT], _MenuCommandT], - collections.Callable[[_MessageCommandT], _MessageCommandT], - collections.Callable[[_SlashCommandT], _SlashCommandT], -]: +) -> ( + collections.Callable[[_CommandT], _CommandT] + | collections.Callable[[_MenuCommandT], _MenuCommandT] + | collections.Callable[[_MessageCommandT], _MessageCommandT] + | collections.Callable[[_SlashCommandT], _SlashCommandT] +): """Add a check which will pass if all the provided checks pass through a decorator call. This ensures that the callbacks are run in the order they were supplied in @@ -1138,8 +1108,8 @@ class _AnyChecks(_Check, typing.Generic[_ContextT]): def __init__( self, checks: list[tanjun.CheckSig[_ContextT]], - error: typing.Optional[collections.Callable[[], Exception]], - error_message: typing.Union[str, collections.Mapping[str, str], None], + error: collections.Callable[[], Exception] | None, + error_message: str | collections.Mapping[str, str] | None, halt_execution: bool, suppress: tuple[type[Exception], ...], ) -> None: @@ -1148,7 +1118,7 @@ def __init__( self._suppress = suppress async def __call__( - self, ctx: _ContextT, /, *, localiser: alluka.Injected[typing.Optional[dependencies.AbstractLocaliser]] = None + self, ctx: _ContextT, /, *, localiser: alluka.Injected[dependencies.AbstractLocaliser | None] = None ) -> bool: for check in self._checks: try: @@ -1168,8 +1138,8 @@ def any_checks( check: tanjun.CheckSig[_ContextT], /, *checks: tanjun.CheckSig[_ContextT], - error: typing.Optional[collections.Callable[[], Exception]] = None, - error_message: typing.Union[str, collections.Mapping[str, str], None], + error: collections.Callable[[], Exception] | None = None, + error_message: str | collections.Mapping[str, str] | None, halt_execution: bool = False, suppress: tuple[type[Exception], ...] = (errors.CommandError, errors.HaltExecution), ) -> _AnyCallback[_ContextT]: @@ -1203,7 +1173,7 @@ def any_checks( Returns ------- - collections.Callable[[tanjun.abc.ExecutableCommand], tanjun.abc.ExecutableCommand] + collections.abc.Callable[[tanjun.abc.ExecutableCommand], tanjun.abc.ExecutableCommand] A decorator which adds the generated check to a command. """ return _AnyChecks[_ContextT]([check, *checks], error, error_message, halt_execution, suppress) @@ -1214,8 +1184,8 @@ def with_any_checks( check: tanjun.AnyCheckSig, /, *checks: tanjun.AnyCheckSig, - error: typing.Optional[collections.Callable[[], Exception]] = None, - error_message: typing.Union[str, collections.Mapping[str, str], None], + error: collections.Callable[[], Exception] | None = None, + error_message: str | collections.Mapping[str, str] | None, follow_wrapped: bool = False, halt_execution: bool = False, suppress: tuple[type[Exception], ...] = (errors.CommandError, errors.HaltExecution), @@ -1227,8 +1197,8 @@ def with_any_checks( check: tanjun.CheckSig[tanjun.MenuContext], /, *checks: tanjun.CheckSig[tanjun.MenuContext], - error: typing.Optional[collections.Callable[[], Exception]] = None, - error_message: typing.Union[str, collections.Mapping[str, str], None], + error: collections.Callable[[], Exception] | None = None, + error_message: str | collections.Mapping[str, str] | None, follow_wrapped: bool = False, halt_execution: bool = False, suppress: tuple[type[Exception], ...] = (errors.CommandError, errors.HaltExecution), @@ -1240,8 +1210,8 @@ def with_any_checks( check: tanjun.CheckSig[tanjun.MessageContext], /, *checks: tanjun.CheckSig[tanjun.MessageContext], - error: typing.Optional[collections.Callable[[], Exception]] = None, - error_message: typing.Union[str, collections.Mapping[str, str], None], + error: collections.Callable[[], Exception] | None = None, + error_message: str | collections.Mapping[str, str] | None, follow_wrapped: bool = False, halt_execution: bool = False, suppress: tuple[type[Exception], ...] = (errors.CommandError, errors.HaltExecution), @@ -1253,8 +1223,8 @@ def with_any_checks( check: tanjun.CheckSig[tanjun.SlashContext], /, *checks: tanjun.CheckSig[tanjun.SlashContext], - error: typing.Optional[collections.Callable[[], Exception]] = None, - error_message: typing.Union[str, collections.Mapping[str, str], None], + error: collections.Callable[[], Exception] | None = None, + error_message: str | collections.Mapping[str, str] | None, follow_wrapped: bool = False, halt_execution: bool = False, suppress: tuple[type[Exception], ...] = (errors.CommandError, errors.HaltExecution), @@ -1265,17 +1235,17 @@ def with_any_checks( check: tanjun.CheckSig[typing.Any], /, *checks: tanjun.CheckSig[typing.Any], - error: typing.Optional[collections.Callable[[], Exception]] = None, - error_message: typing.Union[str, collections.Mapping[str, str], None], + error: collections.Callable[[], Exception] | None = None, + error_message: str | collections.Mapping[str, str] | None, follow_wrapped: bool = False, halt_execution: bool = False, suppress: tuple[type[Exception], ...] = (errors.CommandError, errors.HaltExecution), -) -> typing.Union[ - collections.Callable[[_CommandT], _CommandT], - collections.Callable[[_MenuCommandT], _MenuCommandT], - collections.Callable[[_MessageCommandT], _MessageCommandT], - collections.Callable[[_SlashCommandT], _SlashCommandT], -]: +) -> ( + collections.Callable[[_CommandT], _CommandT] + | collections.Callable[[_MenuCommandT], _MenuCommandT] + | collections.Callable[[_MessageCommandT], _MessageCommandT] + | collections.Callable[[_SlashCommandT], _SlashCommandT] +): """Add a check which'll pass if any of the provided checks pass through a decorator call. This ensures that the callbacks are run in the order they were supplied in @@ -1309,7 +1279,7 @@ def with_any_checks( Returns ------- - collections.Callable[[tanjun.abc.ExecutableCommand], tanjun.abc.ExecutableCommand] + collections.abc.Callable[[tanjun.abc.ExecutableCommand], tanjun.abc.ExecutableCommand] A decorator which adds the generated check to a command. """ return lambda c: _add_to_command( diff --git a/tanjun/clients.py b/tanjun/clients.py index 5784b72bd..ccdd76a37 100644 --- a/tanjun/clients.py +++ b/tanjun/clients.py @@ -72,19 +72,20 @@ if typing.TYPE_CHECKING: import types - - from typing_extensions import Self + from typing import Self _CheckSigT = typing.TypeVar("_CheckSigT", bound=tanjun.AnyCheckSig) - _AppCmdResponse = typing.Union[ - hikari.api.InteractionMessageBuilder, hikari.api.InteractionDeferredBuilder, hikari.api.InteractionModalBuilder - ] + _AppCmdResponse = ( + hikari.api.InteractionMessageBuilder + | hikari.api.InteractionDeferredBuilder + | hikari.api.InteractionModalBuilder + ) _EventT = typing.TypeVar("_EventT", bound=hikari.Event) _ListenerCallbackSigT = typing.TypeVar("_ListenerCallbackSigT", bound=tanjun.ListenerCallbackSig[typing.Any]) _MetaEventSigT = typing.TypeVar("_MetaEventSigT", bound=tanjun.MetaEventSig) _PrefixGetterSigT = typing.TypeVar("_PrefixGetterSigT", bound="PrefixGetterSig") _T = typing.TypeVar("_T") - _P = typing_extensions.ParamSpec("_P") + _P = typing.ParamSpec("_P") _DefaultT = typing.TypeVar("_DefaultT") class _AutocompleteContextMakerProto(typing.Protocol): @@ -93,7 +94,7 @@ def __call__( client: tanjun.Client, interaction: hikari.AutocompleteInteraction, *, - future: typing.Optional[asyncio.Future[hikari.api.InteractionAutocompleteBuilder]] = None, + future: asyncio.Future[hikari.api.InteractionAutocompleteBuilder] | None = None, ) -> context.AutocompleteContext: raise NotImplementedError @@ -105,10 +106,8 @@ def __call__( register_task: collections.Callable[[asyncio.Task[typing.Any]], None], *, default_to_ephemeral: bool = False, - future: typing.Optional[asyncio.Future[_AppCmdResponse]] = None, - on_not_found: typing.Optional[ - collections.Callable[[tanjun.MenuContext], collections.Awaitable[None]] - ] = None, + future: asyncio.Future[_AppCmdResponse] | None = None, + on_not_found: None | collections.Callable[[tanjun.MenuContext], collections.Awaitable[None]] = None, ) -> context.MenuContext: raise NotImplementedError @@ -133,10 +132,8 @@ def __call__( register_task: collections.Callable[[asyncio.Task[typing.Any]], None], *, default_to_ephemeral: bool = False, - future: typing.Optional[asyncio.Future[_AppCmdResponse]] = None, - on_not_found: typing.Optional[ - collections.Callable[[tanjun.SlashContext], collections.Awaitable[None]] - ] = None, + future: asyncio.Future[_AppCmdResponse] | None = None, + on_not_found: None | collections.Callable[[tanjun.SlashContext], collections.Awaitable[None]] = None, ) -> context.SlashContext: raise NotImplementedError @@ -144,22 +141,15 @@ class _GatewayBotProto(hikari.EventManagerAware, hikari.RESTAware, hikari.ShardA """Protocol of a cacheless Hikari Gateway bot.""" -# 3.9 and 3.10 just can't handle ending Concatenate with ... so we lie about this at runtime. -if typing.TYPE_CHECKING: - PrefixGetterSig = collections.Callable[ - typing_extensions.Concatenate[tanjun.MessageContext, ...], - collections.Coroutine[typing.Any, typing.Any, collections.Iterable[str]], - ] - """Type hint of a callable used to get the prefix(es) for a specific guild. - - This represents the callback `async def (tanjun.abc.MessageContext, ...) -> collections.Iterable[str]` - where dependency injection is supported. - """ +PrefixGetterSig = collections.Callable[ + typing.Concatenate[tanjun.MessageContext, ...], + collections.Coroutine[typing.Any, typing.Any, collections.Iterable[str]], +] +"""Type hint of a callable used to get the prefix(es) for a specific guild. -else: - PrefixGetterSig = collections.Callable[ - ..., collections.Coroutine[typing.Any, typing.Any, collections.Iterable[str]] - ] +This represents the callback `async def (tanjun.abc.MessageContext, ...) -> collections.Iterable[str]` +where dependency injection is supported. +""" _LOGGER: typing.Final[logging.Logger] = logging.getLogger("hikari.tanjun.clients") _MENU_TYPES = frozenset((hikari.CommandType.MESSAGE, hikari.CommandType.USER)) @@ -168,7 +158,7 @@ class _GatewayBotProto(hikari.EventManagerAware, hikari.RESTAware, hikari.ShardA class _LoaderDescriptor(tanjun.ClientLoader): # Slots mess with functools.update_wrapper def __init__( self, - callback: typing.Union[collections.Callable[[Client], None], collections.Callable[[tanjun.Client], None]], + callback: collections.Callable[[Client], None] | collections.Callable[[tanjun.Client], None], standard_impl: bool, ) -> None: self._callback = callback @@ -205,7 +195,7 @@ def unload(self, _: tanjun.Client, /) -> bool: class _UnloaderDescriptor(tanjun.ClientLoader): # Slots mess with functools.update_wrapper def __init__( self, - callback: typing.Union[collections.Callable[[Client], None], collections.Callable[[tanjun.Client], None]], + callback: collections.Callable[[Client], None] | collections.Callable[[tanjun.Client], None], standard_impl: bool, ) -> None: self._callback = callback @@ -266,18 +256,16 @@ def as_loader( def as_loader( - callback: typing.Union[ - collections.Callable[[tanjun.Client], None], collections.Callable[[Client], None], None - ] = None, + callback: collections.Callable[[tanjun.Client], None] | collections.Callable[[Client], None] | None = None, /, *, standard_impl: bool = True, -) -> typing.Union[ - collections.Callable[[tanjun.Client], None], - collections.Callable[[Client], None], - collections.Callable[[collections.Callable[[Client], None]], collections.Callable[[Client], None]], - collections.Callable[[collections.Callable[[tanjun.Client], None]], collections.Callable[[tanjun.Client], None]], -]: +) -> ( + collections.Callable[[tanjun.Client], None] + | collections.Callable[[Client], None] + | collections.Callable[[collections.Callable[[Client], None]], collections.Callable[[Client], None]] + | collections.Callable[[collections.Callable[[tanjun.Client], None]], collections.Callable[[tanjun.Client], None]] +): """Mark a callback as being used to load Tanjun components from a module. !!! note @@ -340,18 +328,16 @@ def as_unloader( def as_unloader( - callback: typing.Union[ - collections.Callable[[Client], None], collections.Callable[[tanjun.Client], None], None - ] = None, + callback: collections.Callable[[Client], None] | collections.Callable[[tanjun.Client], None] | None = None, /, *, standard_impl: bool = True, -) -> typing.Union[ - collections.Callable[[Client], None], - collections.Callable[[tanjun.Client], None], - collections.Callable[[collections.Callable[[Client], None]], collections.Callable[[Client], None]], - collections.Callable[[collections.Callable[[tanjun.Client], None]], collections.Callable[[tanjun.Client], None]], -]: +) -> ( + collections.Callable[[Client], None] + | collections.Callable[[tanjun.Client], None] + | collections.Callable[[collections.Callable[[Client], None]], collections.Callable[[Client], None]] + | collections.Callable[[collections.Callable[[tanjun.Client], None]], collections.Callable[[tanjun.Client], None]] +): """Mark a callback as being used to unload a module's utilities from a client. !!! note @@ -427,7 +413,7 @@ class MessageAcceptsEnum(str, enum.Enum): NONE = "NONE" """Set the client to not execute commands based on message create events.""" - def get_event_type(self) -> typing.Optional[type[hikari.MessageCreateEvent]]: + def get_event_type(self) -> type[hikari.MessageCreateEvent] | None: """Get the base event type this mode listens to. Returns @@ -442,7 +428,7 @@ def get_event_type(self) -> typing.Optional[type[hikari.MessageCreateEvent]]: return _ACCEPTS_EVENT_TYPE_MAPPING[self] -_ACCEPTS_EVENT_TYPE_MAPPING: dict[MessageAcceptsEnum, typing.Optional[type[hikari.MessageCreateEvent]]] = { +_ACCEPTS_EVENT_TYPE_MAPPING: dict[MessageAcceptsEnum, type[hikari.MessageCreateEvent] | None] = { MessageAcceptsEnum.ALL: hikari.MessageCreateEvent, MessageAcceptsEnum.DM_ONLY: hikari.DMMessageCreateEvent, MessageAcceptsEnum.GUILD_ONLY: hikari.GuildMessageCreateEvent, @@ -478,9 +464,9 @@ def __init__( self, client: Client, guild_id: hikari.UndefinedOr[hikari.SnowflakeishOr[hikari.PartialGuild]], - command_ids: typing.Optional[collections.Mapping[str, hikari.SnowflakeishOr[hikari.PartialCommand]]], - message_ids: typing.Optional[collections.Mapping[str, hikari.SnowflakeishOr[hikari.PartialCommand]]], - user_ids: typing.Optional[collections.Mapping[str, hikari.SnowflakeishOr[hikari.PartialCommand]]], + command_ids: collections.Mapping[str, hikari.SnowflakeishOr[hikari.PartialCommand]] | None, + message_ids: collections.Mapping[str, hikari.SnowflakeishOr[hikari.PartialCommand]] | None, + user_ids: collections.Mapping[str, hikari.SnowflakeishOr[hikari.PartialCommand]] | None, ) -> None: self.client = client self.command_ids = command_ids @@ -496,11 +482,11 @@ async def __call__(self) -> None: def _log_clients( - cache: typing.Optional[hikari.api.Cache], - events: typing.Optional[hikari.api.EventManager], - server: typing.Optional[hikari.api.InteractionServer], + cache: hikari.api.Cache | None, + events: hikari.api.EventManager | None, + server: hikari.api.InteractionServer | None, rest: hikari.api.RESTClient, - shards: typing.Optional[hikari.ShardAware], + shards: hikari.ShardAware | None, event_managed: bool, /, ) -> None: @@ -582,20 +568,20 @@ def __init__( self, rest: hikari.api.RESTClient, *, - cache: typing.Optional[hikari.api.Cache] = None, - events: typing.Optional[hikari.api.EventManager] = None, - server: typing.Optional[hikari.api.InteractionServer] = None, - shards: typing.Optional[hikari.ShardAware] = None, - voice: typing.Optional[hikari.api.VoiceComponent] = None, + cache: hikari.api.Cache | None = None, + events: hikari.api.EventManager | None = None, + server: hikari.api.InteractionServer | None = None, + shards: hikari.ShardAware | None = None, + voice: hikari.api.VoiceComponent | None = None, event_managed: bool = False, - injector: typing.Optional[alluka.abc.Client] = None, + injector: alluka.abc.Client | None = None, mention_prefix: bool = False, - declare_global_commands: typing.Union[ - hikari.SnowflakeishSequence[hikari.PartialGuild], hikari.SnowflakeishOr[hikari.PartialGuild], bool - ] = False, - command_ids: typing.Optional[collections.Mapping[str, hikari.SnowflakeishOr[hikari.PartialCommand]]] = None, - message_ids: typing.Optional[collections.Mapping[str, hikari.SnowflakeishOr[hikari.PartialCommand]]] = None, - user_ids: typing.Optional[collections.Mapping[str, hikari.SnowflakeishOr[hikari.PartialCommand]]] = None, + declare_global_commands: ( + hikari.SnowflakeishSequence[hikari.PartialGuild] | hikari.SnowflakeishOr[hikari.PartialGuild] | bool + ) = False, + command_ids: collections.Mapping[str, hikari.SnowflakeishOr[hikari.PartialCommand]] | None = None, + message_ids: collections.Mapping[str, hikari.SnowflakeishOr[hikari.PartialCommand]] | None = None, + user_ids: collections.Mapping[str, hikari.SnowflakeishOr[hikari.PartialCommand]] | None = None, ) -> None: ... @typing.overload @@ -604,21 +590,21 @@ def __init__( self, rest: hikari.api.RESTClient, *, - cache: typing.Optional[hikari.api.Cache] = None, - events: typing.Optional[hikari.api.EventManager] = None, - server: typing.Optional[hikari.api.InteractionServer] = None, - shards: typing.Optional[hikari.ShardAware] = None, - voice: typing.Optional[hikari.api.VoiceComponent] = None, + cache: hikari.api.Cache | None = None, + events: hikari.api.EventManager | None = None, + server: hikari.api.InteractionServer | None = None, + shards: hikari.ShardAware | None = None, + voice: hikari.api.VoiceComponent | None = None, event_managed: bool = False, - injector: typing.Optional[alluka.abc.Client] = None, + injector: alluka.abc.Client | None = None, mention_prefix: bool = False, - set_global_commands: typing.Union[hikari.SnowflakeishOr[hikari.PartialGuild], bool] = False, - declare_global_commands: typing.Union[ - hikari.SnowflakeishSequence[hikari.PartialGuild], hikari.SnowflakeishOr[hikari.PartialGuild], bool - ] = False, - command_ids: typing.Optional[collections.Mapping[str, hikari.SnowflakeishOr[hikari.PartialCommand]]] = None, - message_ids: typing.Optional[collections.Mapping[str, hikari.SnowflakeishOr[hikari.PartialCommand]]] = None, - user_ids: typing.Optional[collections.Mapping[str, hikari.SnowflakeishOr[hikari.PartialCommand]]] = None, + set_global_commands: hikari.SnowflakeishOr[hikari.PartialGuild] | bool = False, + declare_global_commands: ( + hikari.SnowflakeishSequence[hikari.PartialGuild] | hikari.SnowflakeishOr[hikari.PartialGuild] | bool + ) = False, + command_ids: collections.Mapping[str, hikari.SnowflakeishOr[hikari.PartialCommand]] | None = None, + message_ids: collections.Mapping[str, hikari.SnowflakeishOr[hikari.PartialCommand]] | None = None, + user_ids: collections.Mapping[str, hikari.SnowflakeishOr[hikari.PartialCommand]] | None = None, _stack_level: int = 0, ) -> None: ... @@ -626,21 +612,21 @@ def __init__( self, rest: hikari.api.RESTClient, *, - cache: typing.Optional[hikari.api.Cache] = None, - events: typing.Optional[hikari.api.EventManager] = None, - server: typing.Optional[hikari.api.InteractionServer] = None, - shards: typing.Optional[hikari.ShardAware] = None, - voice: typing.Optional[hikari.api.VoiceComponent] = None, + cache: hikari.api.Cache | None = None, + events: hikari.api.EventManager | None = None, + server: hikari.api.InteractionServer | None = None, + shards: hikari.ShardAware | None = None, + voice: hikari.api.VoiceComponent | None = None, event_managed: bool = False, - injector: typing.Optional[alluka.abc.Client] = None, + injector: alluka.abc.Client | None = None, mention_prefix: bool = False, - set_global_commands: typing.Union[hikari.SnowflakeishOr[hikari.PartialGuild], bool] = False, - declare_global_commands: typing.Union[ - hikari.SnowflakeishSequence[hikari.PartialGuild], hikari.SnowflakeishOr[hikari.PartialGuild], bool - ] = False, - command_ids: typing.Optional[collections.Mapping[str, hikari.SnowflakeishOr[hikari.PartialCommand]]] = None, - message_ids: typing.Optional[collections.Mapping[str, hikari.SnowflakeishOr[hikari.PartialCommand]]] = None, - user_ids: typing.Optional[collections.Mapping[str, hikari.SnowflakeishOr[hikari.PartialCommand]]] = None, + set_global_commands: hikari.SnowflakeishOr[hikari.PartialGuild] | bool = False, + declare_global_commands: ( + hikari.SnowflakeishSequence[hikari.PartialGuild] | hikari.SnowflakeishOr[hikari.PartialGuild] | bool + ) = False, + command_ids: collections.Mapping[str, hikari.SnowflakeishOr[hikari.PartialCommand]] | None = None, + message_ids: collections.Mapping[str, hikari.SnowflakeishOr[hikari.PartialCommand]] | None = None, + user_ids: collections.Mapping[str, hikari.SnowflakeishOr[hikari.PartialCommand]] | None = None, _stack_level: int = 0, ) -> None: """Initialise a Tanjun client. @@ -740,9 +726,9 @@ def __init__( "automatic command dispatch will be unavailable." ) - self._auto_defer_after: typing.Optional[float] = 2.0 + self._auto_defer_after: float | None = 2.0 self._cache = cache - self._cached_application_id: typing.Optional[hikari.Snowflake] = None + self._cached_application_id: hikari.Snowflake | None = None self._checks: list[tanjun.AnyCheckSig] = [] self._client_callbacks: dict[str, list[tanjun.MetaEventSig]] = {} self._components: dict[str, tanjun.Component] = {} @@ -751,30 +737,30 @@ def __init__( self._dms_enabled_for_app_cmds = True self._events = events self._grab_mention_prefix = mention_prefix - self._hooks: typing.Optional[tanjun.AnyHooks] = hooks.AnyHooks().set_on_parser_error(on_parser_error) + self._hooks: tanjun.AnyHooks | None = hooks.AnyHooks().set_on_parser_error(on_parser_error) self._interaction_accepts = InteractionAcceptsEnum.ALL self._is_case_sensitive = True - self._menu_hooks: typing.Optional[tanjun.MenuHooks] = None - self._menu_not_found: typing.Optional[str] = "Command not found" - self._slash_hooks: typing.Optional[tanjun.SlashHooks] = None - self._slash_not_found: typing.Optional[str] = self._menu_not_found + self._menu_hooks: tanjun.MenuHooks | None = None + self._menu_not_found: str | None = "Command not found" + self._slash_hooks: tanjun.SlashHooks | None = None + self._slash_not_found: str | None = self._menu_not_found # TODO: test coverage self._injector = injector or alluka.Client() self._is_closing = False self._listeners: dict[ type[hikari.Event], dict[tanjun.ListenerCallbackSig[typing.Any], tanjun.ListenerCallbackSig[typing.Any]] ] = {} - self._loop: typing.Optional[asyncio.AbstractEventLoop] = None + self._loop: asyncio.AbstractEventLoop | None = None self._make_autocomplete_context: _AutocompleteContextMakerProto = context.AutocompleteContext self._make_menu_context: _MenuContextMakerProto = context.MenuContext self._make_message_context: _MessageContextMakerProto = context.MessageContext self._make_slash_context: _SlashContextMakerProto = context.SlashContext self._message_accepts = MessageAcceptsEnum.ALL if events else MessageAcceptsEnum.NONE - self._message_hooks: typing.Optional[tanjun.MessageHooks] = None + self._message_hooks: tanjun.MessageHooks | None = None self._metadata: dict[typing.Any, typing.Any] = {} self._modules: dict[str, types.ModuleType] = {} self._path_modules: dict[pathlib.Path, types.ModuleType] = {} - self._prefix_getter: typing.Optional[PrefixGetterSig] = None + self._prefix_getter: PrefixGetterSig | None = None self._prefixes: list[str] = [] self._rest = rest self._server = server @@ -817,7 +803,7 @@ def __init__( _stack_level=_stack_level, ) - def _maybe_set_type_dep(self, type_: type[_T], value: typing.Optional[_T], /) -> Self: + def _maybe_set_type_dep(self, type_: type[_T], value: _T | None, /) -> Self: if value is not None: self.set_type_dependency(type_, value) @@ -825,13 +811,13 @@ def _maybe_set_type_dep(self, type_: type[_T], value: typing.Optional[_T], /) -> def _schedule_startup_registers( self, - set_global_commands: typing.Union[hikari.SnowflakeishOr[hikari.PartialGuild], bool] = False, - declare_global_commands: typing.Union[ - hikari.SnowflakeishSequence[hikari.PartialGuild], hikari.SnowflakeishOr[hikari.PartialGuild], bool - ] = False, - command_ids: typing.Optional[collections.Mapping[str, hikari.SnowflakeishOr[hikari.PartialCommand]]] = None, - message_ids: typing.Optional[collections.Mapping[str, hikari.SnowflakeishOr[hikari.PartialCommand]]] = None, - user_ids: typing.Optional[collections.Mapping[str, hikari.SnowflakeishOr[hikari.PartialCommand]]] = None, + set_global_commands: hikari.SnowflakeishOr[hikari.PartialGuild] | bool = False, + declare_global_commands: ( + hikari.SnowflakeishSequence[hikari.PartialGuild] | hikari.SnowflakeishOr[hikari.PartialGuild] | bool + ) = False, + command_ids: collections.Mapping[str, hikari.SnowflakeishOr[hikari.PartialCommand]] | None = None, + message_ids: collections.Mapping[str, hikari.SnowflakeishOr[hikari.PartialCommand]] | None = None, + user_ids: collections.Mapping[str, hikari.SnowflakeishOr[hikari.PartialCommand]] | None = None, _stack_level: int = 0, ) -> None: if set_global_commands: @@ -900,14 +886,14 @@ def from_gateway_bot( /, *, event_managed: bool = True, - injector: typing.Optional[alluka.abc.Client] = None, + injector: alluka.abc.Client | None = None, mention_prefix: bool = False, - declare_global_commands: typing.Union[ - hikari.SnowflakeishSequence[hikari.PartialGuild], hikari.SnowflakeishOr[hikari.PartialGuild], bool - ] = False, - command_ids: typing.Optional[collections.Mapping[str, hikari.SnowflakeishOr[hikari.PartialCommand]]] = None, - message_ids: typing.Optional[collections.Mapping[str, hikari.SnowflakeishOr[hikari.PartialCommand]]] = None, - user_ids: typing.Optional[collections.Mapping[str, hikari.SnowflakeishOr[hikari.PartialCommand]]] = None, + declare_global_commands: ( + hikari.SnowflakeishSequence[hikari.PartialGuild] | hikari.SnowflakeishOr[hikari.PartialGuild] | bool + ) = False, + command_ids: collections.Mapping[str, hikari.SnowflakeishOr[hikari.PartialCommand]] | None = None, + message_ids: collections.Mapping[str, hikari.SnowflakeishOr[hikari.PartialCommand]] | None = None, + user_ids: collections.Mapping[str, hikari.SnowflakeishOr[hikari.PartialCommand]] | None = None, ) -> Client: ... @classmethod @@ -919,15 +905,15 @@ def from_gateway_bot( /, *, event_managed: bool = True, - injector: typing.Optional[alluka.abc.Client] = None, + injector: alluka.abc.Client | None = None, mention_prefix: bool = False, - declare_global_commands: typing.Union[ - hikari.SnowflakeishSequence[hikari.PartialGuild], hikari.SnowflakeishOr[hikari.PartialGuild], bool - ] = False, - set_global_commands: typing.Union[hikari.SnowflakeishOr[hikari.PartialGuild], bool] = False, - command_ids: typing.Optional[collections.Mapping[str, hikari.SnowflakeishOr[hikari.PartialCommand]]] = None, - message_ids: typing.Optional[collections.Mapping[str, hikari.SnowflakeishOr[hikari.PartialCommand]]] = None, - user_ids: typing.Optional[collections.Mapping[str, hikari.SnowflakeishOr[hikari.PartialCommand]]] = None, + declare_global_commands: ( + hikari.SnowflakeishSequence[hikari.PartialGuild] | hikari.SnowflakeishOr[hikari.PartialGuild] | bool + ) = False, + set_global_commands: hikari.SnowflakeishOr[hikari.PartialGuild] | bool = False, + command_ids: collections.Mapping[str, hikari.SnowflakeishOr[hikari.PartialCommand]] | None = None, + message_ids: collections.Mapping[str, hikari.SnowflakeishOr[hikari.PartialCommand]] | None = None, + user_ids: collections.Mapping[str, hikari.SnowflakeishOr[hikari.PartialCommand]] | None = None, ) -> Client: ... @classmethod @@ -937,15 +923,15 @@ def from_gateway_bot( /, *, event_managed: bool = True, - injector: typing.Optional[alluka.abc.Client] = None, + injector: alluka.abc.Client | None = None, mention_prefix: bool = False, - declare_global_commands: typing.Union[ - hikari.SnowflakeishSequence[hikari.PartialGuild], hikari.SnowflakeishOr[hikari.PartialGuild], bool - ] = False, - set_global_commands: typing.Union[hikari.SnowflakeishOr[hikari.PartialGuild], bool] = False, - command_ids: typing.Optional[collections.Mapping[str, hikari.SnowflakeishOr[hikari.PartialCommand]]] = None, - message_ids: typing.Optional[collections.Mapping[str, hikari.SnowflakeishOr[hikari.PartialCommand]]] = None, - user_ids: typing.Optional[collections.Mapping[str, hikari.SnowflakeishOr[hikari.PartialCommand]]] = None, + declare_global_commands: ( + hikari.SnowflakeishSequence[hikari.PartialGuild] | hikari.SnowflakeishOr[hikari.PartialGuild] | bool + ) = False, + set_global_commands: hikari.SnowflakeishOr[hikari.PartialGuild] | bool = False, + command_ids: collections.Mapping[str, hikari.SnowflakeishOr[hikari.PartialCommand]] | None = None, + message_ids: collections.Mapping[str, hikari.SnowflakeishOr[hikari.PartialCommand]] | None = None, + user_ids: collections.Mapping[str, hikari.SnowflakeishOr[hikari.PartialCommand]] | None = None, ) -> Client: """Build a [Client][tanjun.Client] from a gateway bot. @@ -1030,13 +1016,13 @@ def from_rest_bot( /, *, bot_managed: bool = False, - declare_global_commands: typing.Union[ - hikari.SnowflakeishSequence[hikari.PartialGuild], hikari.SnowflakeishOr[hikari.PartialGuild], bool - ] = False, - injector: typing.Optional[alluka.abc.Client] = None, - command_ids: typing.Optional[collections.Mapping[str, hikari.SnowflakeishOr[hikari.PartialCommand]]] = None, - message_ids: typing.Optional[collections.Mapping[str, hikari.SnowflakeishOr[hikari.PartialCommand]]] = None, - user_ids: typing.Optional[collections.Mapping[str, hikari.SnowflakeishOr[hikari.PartialCommand]]] = None, + declare_global_commands: ( + hikari.SnowflakeishSequence[hikari.PartialGuild] | hikari.SnowflakeishOr[hikari.PartialGuild] | bool + ) = False, + injector: alluka.abc.Client | None = None, + command_ids: collections.Mapping[str, hikari.SnowflakeishOr[hikari.PartialCommand]] | None = None, + message_ids: collections.Mapping[str, hikari.SnowflakeishOr[hikari.PartialCommand]] | None = None, + user_ids: collections.Mapping[str, hikari.SnowflakeishOr[hikari.PartialCommand]] | None = None, ) -> Client: ... @classmethod @@ -1048,14 +1034,14 @@ def from_rest_bot( /, *, bot_managed: bool = False, - declare_global_commands: typing.Union[ - hikari.SnowflakeishSequence[hikari.PartialGuild], hikari.SnowflakeishOr[hikari.PartialGuild], bool - ] = False, - injector: typing.Optional[alluka.abc.Client] = None, - set_global_commands: typing.Union[hikari.SnowflakeishOr[hikari.PartialGuild], bool] = False, - command_ids: typing.Optional[collections.Mapping[str, hikari.SnowflakeishOr[hikari.PartialCommand]]] = None, - message_ids: typing.Optional[collections.Mapping[str, hikari.SnowflakeishOr[hikari.PartialCommand]]] = None, - user_ids: typing.Optional[collections.Mapping[str, hikari.SnowflakeishOr[hikari.PartialCommand]]] = None, + declare_global_commands: ( + hikari.SnowflakeishSequence[hikari.PartialGuild] | hikari.SnowflakeishOr[hikari.PartialGuild] | bool + ) = False, + injector: alluka.abc.Client | None = None, + set_global_commands: hikari.SnowflakeishOr[hikari.PartialGuild] | bool = False, + command_ids: collections.Mapping[str, hikari.SnowflakeishOr[hikari.PartialCommand]] | None = None, + message_ids: collections.Mapping[str, hikari.SnowflakeishOr[hikari.PartialCommand]] | None = None, + user_ids: collections.Mapping[str, hikari.SnowflakeishOr[hikari.PartialCommand]] | None = None, ) -> Client: ... @classmethod @@ -1065,14 +1051,14 @@ def from_rest_bot( /, *, bot_managed: bool = False, - declare_global_commands: typing.Union[ - hikari.SnowflakeishSequence[hikari.PartialGuild], hikari.SnowflakeishOr[hikari.PartialGuild], bool - ] = False, - injector: typing.Optional[alluka.abc.Client] = None, - set_global_commands: typing.Union[hikari.SnowflakeishOr[hikari.PartialGuild], bool] = False, - command_ids: typing.Optional[collections.Mapping[str, hikari.SnowflakeishOr[hikari.PartialCommand]]] = None, - message_ids: typing.Optional[collections.Mapping[str, hikari.SnowflakeishOr[hikari.PartialCommand]]] = None, - user_ids: typing.Optional[collections.Mapping[str, hikari.SnowflakeishOr[hikari.PartialCommand]]] = None, + declare_global_commands: ( + hikari.SnowflakeishSequence[hikari.PartialGuild] | hikari.SnowflakeishOr[hikari.PartialGuild] | bool + ) = False, + injector: alluka.abc.Client | None = None, + set_global_commands: hikari.SnowflakeishOr[hikari.PartialGuild] | bool = False, + command_ids: collections.Mapping[str, hikari.SnowflakeishOr[hikari.PartialCommand]] | None = None, + message_ids: collections.Mapping[str, hikari.SnowflakeishOr[hikari.PartialCommand]] | None = None, + user_ids: collections.Mapping[str, hikari.SnowflakeishOr[hikari.PartialCommand]] | None = None, ) -> Client: """Build a [Client][tanjun.Client] from a [hikari.RESTBotAware][hikari.traits.RESTBotAware] instance. @@ -1149,10 +1135,7 @@ async def __aenter__(self) -> Client: return self async def __aexit__( - self, - exc_type: typing.Optional[type[BaseException]], - exc: typing.Optional[BaseException], - exc_traceback: typing.Optional[types.TracebackType], + self, exc_type: type[BaseException] | None, exc: BaseException | None, exc_traceback: types.TracebackType | None ) -> None: await self.close() @@ -1195,7 +1178,7 @@ def is_human_only(self) -> bool: return _check_human in self._checks @property - def cache(self) -> typing.Optional[hikari.api.Cache]: + def cache(self) -> hikari.api.Cache | None: # <>. return self._cache @@ -1214,7 +1197,7 @@ def components(self) -> collections.Collection[tanjun.Component]: return self._components.copy().values() @property - def events(self) -> typing.Optional[hikari.api.EventManager]: + def events(self) -> hikari.api.EventManager | None: # <>. return self._events @@ -1236,12 +1219,12 @@ def is_case_sensitive(self) -> bool: return self._is_case_sensitive @property - def loop(self) -> typing.Optional[asyncio.AbstractEventLoop]: + def loop(self) -> asyncio.AbstractEventLoop | None: # <>. return self._loop @property - def hooks(self) -> typing.Optional[tanjun.AnyHooks]: + def hooks(self) -> tanjun.AnyHooks | None: """Top level [tanjun.abc.AnyHooks][] set for this client. These are called during both message, menu and slash command execution. @@ -1249,7 +1232,7 @@ def hooks(self) -> typing.Optional[tanjun.AnyHooks]: return self._hooks @property - def menu_hooks(self) -> typing.Optional[tanjun.MenuHooks]: + def menu_hooks(self) -> tanjun.MenuHooks | None: """Top level [tanjun.abc.MenuHooks][] set for this client. These are only called during menu command execution. @@ -1257,7 +1240,7 @@ def menu_hooks(self) -> typing.Optional[tanjun.MenuHooks]: return self._menu_hooks @property - def message_hooks(self) -> typing.Optional[tanjun.MessageHooks]: + def message_hooks(self) -> tanjun.MessageHooks | None: """Top level [tanjun.abc.MessageHooks][] set for this client. These are only called during message command execution. @@ -1265,7 +1248,7 @@ def message_hooks(self) -> typing.Optional[tanjun.MessageHooks]: return self._message_hooks @property - def slash_hooks(self) -> typing.Optional[tanjun.SlashHooks]: + def slash_hooks(self) -> tanjun.SlashHooks | None: """Top level [tanjun.abc.SlashHooks][] set for this client. These are only called during slash command execution. @@ -1278,7 +1261,7 @@ def metadata(self) -> collections.MutableMapping[typing.Any, typing.Any]: return self._metadata @property - def prefix_getter(self) -> typing.Optional[PrefixGetterSig]: + def prefix_getter(self) -> PrefixGetterSig | None: """Prefix getter method set for this client. For more information on this callback's signature see @@ -1297,30 +1280,30 @@ def rest(self) -> hikari.api.RESTClient: return self._rest @property - def server(self) -> typing.Optional[hikari.api.InteractionServer]: + def server(self) -> hikari.api.InteractionServer | None: # <>. return self._server @property - def shards(self) -> typing.Optional[hikari.ShardAware]: + def shards(self) -> hikari.ShardAware | None: # <>. return self._shards @property - def voice(self) -> typing.Optional[hikari.api.VoiceComponent]: + def voice(self) -> hikari.api.VoiceComponent | None: # <>. return self._voice - async def _on_starting(self, _: typing.Union[hikari.StartingEvent, hikari.RESTBotAware], /) -> None: + async def _on_starting(self, _: hikari.StartingEvent | hikari.RESTBotAware, /) -> None: await self.open() - async def _on_stopping(self, _: typing.Union[hikari.StoppingEvent, hikari.RESTBotAware], /) -> None: + async def _on_stopping(self, _: hikari.StoppingEvent | hikari.RESTBotAware, /) -> None: await self.close() async def clear_application_commands( self, *, - application: typing.Optional[hikari.SnowflakeishOr[hikari.PartialApplication]] = None, + application: hikari.SnowflakeishOr[hikari.PartialApplication] | None = None, guild: hikari.UndefinedOr[hikari.SnowflakeishOr[hikari.PartialGuild]] = hikari.UNDEFINED, ) -> None: # <>. @@ -1333,7 +1316,7 @@ async def clear_application_commands( async def set_global_commands( self, *, - application: typing.Optional[hikari.SnowflakeishOr[hikari.PartialApplication]] = None, + application: hikari.SnowflakeishOr[hikari.PartialApplication] | None = None, guild: hikari.UndefinedOr[hikari.SnowflakeishOr[hikari.PartialGuild]] = hikari.UNDEFINED, force: bool = False, ) -> collections.Sequence[hikari.PartialCommand]: @@ -1347,12 +1330,12 @@ async def set_global_commands( async def declare_global_commands( self, - command_ids: typing.Optional[collections.Mapping[str, hikari.SnowflakeishOr[hikari.PartialCommand]]] = None, + command_ids: collections.Mapping[str, hikari.SnowflakeishOr[hikari.PartialCommand]] | None = None, *, - application: typing.Optional[hikari.SnowflakeishOr[hikari.PartialApplication]] = None, + application: hikari.SnowflakeishOr[hikari.PartialApplication] | None = None, guild: hikari.UndefinedOr[hikari.SnowflakeishOr[hikari.PartialGuild]] = hikari.UNDEFINED, - message_ids: typing.Optional[collections.Mapping[str, hikari.SnowflakeishOr[hikari.PartialCommand]]] = None, - user_ids: typing.Optional[collections.Mapping[str, hikari.SnowflakeishOr[hikari.PartialCommand]]] = None, + message_ids: collections.Mapping[str, hikari.SnowflakeishOr[hikari.PartialCommand]] | None = None, + user_ids: collections.Mapping[str, hikari.SnowflakeishOr[hikari.PartialCommand]] | None = None, force: bool = False, ) -> collections.Sequence[hikari.PartialCommand]: # <>. @@ -1374,9 +1357,9 @@ async def declare_application_command( self, command: tanjun.BaseSlashCommand, /, - command_id: typing.Optional[hikari.Snowflakeish] = None, + command_id: hikari.Snowflakeish | None = None, *, - application: typing.Optional[hikari.SnowflakeishOr[hikari.PartialApplication]] = None, + application: hikari.SnowflakeishOr[hikari.PartialApplication] | None = None, guild: hikari.UndefinedOr[hikari.SnowflakeishOr[hikari.PartialGuild]] = hikari.UNDEFINED, ) -> hikari.SlashCommand: ... @@ -1385,9 +1368,9 @@ async def declare_application_command( self, command: tanjun.MenuCommand[typing.Any, typing.Any], /, - command_id: typing.Optional[hikari.Snowflakeish] = None, + command_id: hikari.Snowflakeish | None = None, *, - application: typing.Optional[hikari.SnowflakeishOr[hikari.PartialApplication]] = None, + application: hikari.SnowflakeishOr[hikari.PartialApplication] | None = None, guild: hikari.UndefinedOr[hikari.SnowflakeishOr[hikari.PartialGuild]] = hikari.UNDEFINED, ) -> hikari.ContextMenuCommand: ... @@ -1396,9 +1379,9 @@ async def declare_application_command( self, command: tanjun.AppCommand[typing.Any], /, - command_id: typing.Optional[hikari.Snowflakeish] = None, + command_id: hikari.Snowflakeish | None = None, *, - application: typing.Optional[hikari.SnowflakeishOr[hikari.PartialApplication]] = None, + application: hikari.SnowflakeishOr[hikari.PartialApplication] | None = None, guild: hikari.UndefinedOr[hikari.SnowflakeishOr[hikari.PartialGuild]] = hikari.UNDEFINED, ) -> hikari.PartialCommand: ... @@ -1406,9 +1389,9 @@ async def declare_application_command( self, command: tanjun.AppCommand[typing.Any], /, - command_id: typing.Optional[hikari.Snowflakeish] = None, + command_id: hikari.Snowflakeish | None = None, *, - application: typing.Optional[hikari.SnowflakeishOr[hikari.PartialApplication]] = None, + application: hikari.SnowflakeishOr[hikari.PartialApplication] | None = None, guild: hikari.UndefinedOr[hikari.SnowflakeishOr[hikari.PartialGuild]] = hikari.UNDEFINED, ) -> hikari.PartialCommand: # <>. @@ -1443,14 +1426,14 @@ async def declare_application_command( async def declare_application_commands( self, - commands: collections.Iterable[typing.Union[tanjun.AppCommand[typing.Any], hikari.api.CommandBuilder]], + commands: collections.Iterable[tanjun.AppCommand[typing.Any] | hikari.api.CommandBuilder], /, - command_ids: typing.Optional[collections.Mapping[str, hikari.SnowflakeishOr[hikari.PartialCommand]]] = None, + command_ids: collections.Mapping[str, hikari.SnowflakeishOr[hikari.PartialCommand]] | None = None, *, - application: typing.Optional[hikari.SnowflakeishOr[hikari.PartialApplication]] = None, + application: hikari.SnowflakeishOr[hikari.PartialApplication] | None = None, guild: hikari.UndefinedOr[hikari.SnowflakeishOr[hikari.PartialGuild]] = hikari.UNDEFINED, - message_ids: typing.Optional[collections.Mapping[str, hikari.SnowflakeishOr[hikari.PartialCommand]]] = None, - user_ids: typing.Optional[collections.Mapping[str, hikari.SnowflakeishOr[hikari.PartialCommand]]] = None, + message_ids: collections.Mapping[str, hikari.SnowflakeishOr[hikari.PartialCommand]] | None = None, + user_ids: collections.Mapping[str, hikari.SnowflakeishOr[hikari.PartialCommand]] | None = None, force: bool = False, ) -> collections.Sequence[hikari.PartialCommand]: # <>. @@ -1546,7 +1529,7 @@ async def declare_application_commands( return responses - def set_auto_defer_after(self, time: typing.Optional[float], /) -> Self: + def set_auto_defer_after(self, time: float | None, /) -> Self: """Set when this client should automatically defer execution of commands. !!! warning @@ -1574,7 +1557,7 @@ def set_case_sensitive(self, state: bool, /) -> Self: self._is_case_sensitive = state return self - def set_default_app_command_permissions(self, permissions: typing.Union[int, hikari.Permissions], /) -> Self: + def set_default_app_command_permissions(self, permissions: int | hikari.Permissions, /) -> Self: """Set the default member permissions needed for this client's commands. !!! warning @@ -1660,7 +1643,7 @@ def set_hikari_trait_injectors(self, bot: hikari.RESTAware, /) -> Self: return self - def set_interaction_not_found(self, message: typing.Optional[str], /) -> Self: + def set_interaction_not_found(self, message: str | None, /) -> Self: """Set the response message for when an interaction command is not found. !!! warning @@ -1675,7 +1658,7 @@ def set_interaction_not_found(self, message: typing.Optional[str], /) -> Self: """ return self.set_menu_not_found(message).set_slash_not_found(message) - def set_menu_not_found(self, message: typing.Optional[str], /) -> Self: + def set_menu_not_found(self, message: str | None, /) -> Self: """Set the response message for when a menu command is not found. !!! warning @@ -1691,7 +1674,7 @@ def set_menu_not_found(self, message: typing.Optional[str], /) -> Self: self._menu_not_found = message return self - def set_slash_not_found(self, message: typing.Optional[str], /) -> Self: + def set_slash_not_found(self, message: str | None, /) -> Self: """Set the response message for when a slash command is not found. !!! warning @@ -1986,7 +1969,7 @@ def add_component(self, component: tanjun.Component, /) -> Self: return self - def get_component_by_name(self, name: str, /) -> typing.Optional[tanjun.Component]: + def get_component_by_name(self, name: str, /) -> tanjun.Component | None: # <>. return self._components.get(name) @@ -2015,9 +1998,7 @@ def remove_component_by_name(self, name: str, /) -> Self: # <>. return self.remove_component(self._components[name]) - def add_client_callback( - self, name: typing.Union[str, tanjun.ClientCallbackNames], /, *callbacks: tanjun.MetaEventSig - ) -> Self: + def add_client_callback(self, name: str | tanjun.ClientCallbackNames, /, *callbacks: tanjun.MetaEventSig) -> Self: # <>. name = name.casefold() for callback in callbacks: @@ -2033,9 +2014,7 @@ def add_client_callback( return self - async def dispatch_client_callback( - self, name: typing.Union[str, tanjun.ClientCallbackNames], /, *args: typing.Any - ) -> None: + async def dispatch_client_callback(self, name: str | tanjun.ClientCallbackNames, /, *args: typing.Any) -> None: # <>. name = name.casefold() if callbacks := self._client_callbacks.get(name): @@ -2043,7 +2022,7 @@ async def dispatch_client_callback( await asyncio.gather(*calls) def get_client_callbacks( - self, name: typing.Union[str, tanjun.ClientCallbackNames], / + self, name: str | tanjun.ClientCallbackNames, / ) -> collections.Collection[tanjun.MetaEventSig]: # <>. name = name.casefold() @@ -2052,9 +2031,7 @@ def get_client_callbacks( return () - def remove_client_callback( - self, name: typing.Union[str, tanjun.ClientCallbackNames], callback: tanjun.MetaEventSig, / - ) -> Self: + def remove_client_callback(self, name: str | tanjun.ClientCallbackNames, callback: tanjun.MetaEventSig, /) -> Self: # <>. name = name.casefold() self._client_callbacks[name].remove(callback) @@ -2064,7 +2041,7 @@ def remove_client_callback( return self def with_client_callback( - self, name: typing.Union[str, tanjun.ClientCallbackNames], / + self, name: str | tanjun.ClientCallbackNames, / ) -> collections.Callable[[_MetaEventSigT], _MetaEventSigT]: # <>. def decorator(callback: _MetaEventSigT, /) -> _MetaEventSigT: @@ -2121,7 +2098,7 @@ def decorator(callback: _ListenerCallbackSigT, /) -> _ListenerCallbackSigT: return decorator - def add_prefix(self, prefixes: typing.Union[collections.Iterable[str], str], /) -> Self: + def add_prefix(self, prefixes: collections.Iterable[str] | str, /) -> Self: """Add a prefix used to filter message command calls. This will be matched against the first character(s) in a message's @@ -2169,7 +2146,7 @@ def remove_prefix(self, prefix: str, /) -> Self: self._prefixes.remove(prefix) return self - def set_prefix_getter(self, getter: typing.Optional[PrefixGetterSig], /) -> Self: + def set_prefix_getter(self, getter: PrefixGetterSig | None, /) -> Self: """Set the callback used to retrieve message prefixes set for the relevant guild. Parameters @@ -2242,11 +2219,11 @@ def iter_menu_commands( @typing.overload def iter_menu_commands( - self, *, global_only: bool = False, type: typing.Optional[hikari.CommandType] = None # noqa: A002. + self, *, global_only: bool = False, type: hikari.CommandType | None = None # noqa: A002. ) -> collections.Iterator[tanjun.MenuCommand[typing.Any, typing.Any]]: ... def iter_menu_commands( - self, *, global_only: bool = False, type: typing.Optional[hikari.CommandType] = None # noqa: A002 + self, *, global_only: bool = False, type: hikari.CommandType | None = None # noqa: A002 ) -> collections.Iterator[tanjun.MenuCommand[typing.Any, typing.Any]]: # <>. if global_only: @@ -2285,7 +2262,7 @@ def check_slash_name(self, name: str, /) -> collections.Iterator[tanjun.BaseSlas component.check_slash_name(name) for component in self._components.values() ) - async def _check_prefix(self, ctx: tanjun.MessageContext, /) -> typing.Optional[str]: + async def _check_prefix(self, ctx: tanjun.MessageContext, /) -> str | None: prefix: str # MyPy fubs up its introspection here so we explicitly annotate. if self._prefix_getter: for prefix in await ctx.call_with_async_di(self._prefix_getter, ctx): @@ -2364,7 +2341,7 @@ async def open(self, *, register_listeners: bool = True) -> None: await self.dispatch_client_callback(ClientCallbackNames.STARTING) if self._grab_mention_prefix: - user: typing.Optional[hikari.OwnUser] = None + user: hikari.OwnUser | None = None if self._cache: user = self._cache.get_me() @@ -2435,7 +2412,7 @@ async def fetch_rest_application_id(self) -> hikari.Snowflake: return self._cached_application_id - def set_hooks(self, hooks: typing.Optional[tanjun.AnyHooks], /) -> Self: + def set_hooks(self, hooks: tanjun.AnyHooks | None, /) -> Self: """Set the general command execution hooks for this client. The callbacks within this hook will be added to every slash and message @@ -2456,7 +2433,7 @@ def set_hooks(self, hooks: typing.Optional[tanjun.AnyHooks], /) -> Self: self._hooks = hooks return self - def set_menu_hooks(self, hooks: typing.Optional[tanjun.MenuHooks], /) -> Self: + def set_menu_hooks(self, hooks: tanjun.MenuHooks | None, /) -> Self: """Set the menu command execution hooks for this client. The callbacks within this hook will be added to every menu command @@ -2478,7 +2455,7 @@ def set_menu_hooks(self, hooks: typing.Optional[tanjun.MenuHooks], /) -> Self: self._menu_hooks = hooks return self - def set_slash_hooks(self, hooks: typing.Optional[tanjun.SlashHooks], /) -> Self: + def set_slash_hooks(self, hooks: tanjun.SlashHooks | None, /) -> Self: """Set the slash command execution hooks for this client. The callbacks within this hook will be added to every slash command @@ -2500,7 +2477,7 @@ def set_slash_hooks(self, hooks: typing.Optional[tanjun.SlashHooks], /) -> Self: self._slash_hooks = hooks return self - def set_message_hooks(self, hooks: typing.Optional[tanjun.MessageHooks], /) -> Self: + def set_message_hooks(self, hooks: tanjun.MessageHooks | None, /) -> Self: """Set the message command execution hooks for this client. The callbacks within this hook will be added to every message command @@ -2522,9 +2499,7 @@ def set_message_hooks(self, hooks: typing.Optional[tanjun.MessageHooks], /) -> S self._message_hooks = hooks return self - def load_directory( - self, directory: typing.Union[str, pathlib.Path], /, *, namespace: typing.Optional[str] = None - ) -> Self: + def load_directory(self, directory: str | pathlib.Path, /, *, namespace: str | None = None) -> Self: # <>. paths = _scan_directory(pathlib.Path(directory), namespace) for path in paths: @@ -2537,9 +2512,7 @@ def load_directory( return self - async def load_directory_async( - self, directory: typing.Union[str, pathlib.Path], /, *, namespace: typing.Optional[str] = None - ) -> None: + async def load_directory_async(self, directory: str | pathlib.Path, /, *, namespace: str | None = None) -> None: # <>. paths = await asyncio.get_running_loop().run_in_executor( None, _scan_directory, pathlib.Path(directory), namespace @@ -2552,9 +2525,7 @@ async def load_directory_async( except errors.ModuleMissingLoaders: _LOGGER.info("Ignoring load_directory target `%s` with no loaders", path) - def _call_loaders( - self, module_path: typing.Union[str, pathlib.Path], loaders: list[tanjun.ClientLoader], / - ) -> None: + def _call_loaders(self, module_path: str | pathlib.Path, loaders: list[tanjun.ClientLoader], /) -> None: found = False for loader in loaders: if loader.load(self): @@ -2563,9 +2534,7 @@ def _call_loaders( if not found: raise errors.ModuleMissingLoaders(f"Didn't find any loaders in {module_path}", module_path) - def _call_unloaders( - self, module_path: typing.Union[str, pathlib.Path], loaders: list[tanjun.ClientLoader], / - ) -> None: + def _call_unloaders(self, module_path: str | pathlib.Path, loaders: list[tanjun.ClientLoader], /) -> None: found = False for loader in loaders: if loader.unload(self): @@ -2575,7 +2544,7 @@ def _call_unloaders( raise errors.ModuleMissingUnloaders(f"Didn't find any unloaders in {module_path}", module_path) def _load_module( - self, module_path: typing.Union[str, pathlib.Path], / + self, module_path: str | pathlib.Path, / ) -> collections.Generator[collections.Callable[[], types.ModuleType], types.ModuleType, None]: if isinstance(module_path, str): if module_path in self._modules: @@ -2601,7 +2570,7 @@ def _load_module( self._path_modules[module_path] = module - def load_modules(self, *modules: typing.Union[str, pathlib.Path]) -> Self: + def load_modules(self, *modules: str | pathlib.Path) -> Self: # <>. for module_path in modules: if isinstance(module_path, pathlib.Path): @@ -2621,7 +2590,7 @@ def load_modules(self, *modules: typing.Union[str, pathlib.Path]) -> Self: return self - async def load_modules_async(self, *modules: typing.Union[str, pathlib.Path]) -> None: + async def load_modules_async(self, *modules: str | pathlib.Path) -> None: # <>. loop = asyncio.get_running_loop() for module_path in modules: @@ -2640,7 +2609,7 @@ async def load_modules_async(self, *modules: typing.Union[str, pathlib.Path]) -> else: raise RuntimeError("Generator didn't finish") - def unload_modules(self, *modules: typing.Union[str, pathlib.Path]) -> Self: + def unload_modules(self, *modules: str | pathlib.Path) -> Self: # <>. for module_path in modules: if isinstance(module_path, str): @@ -2663,11 +2632,11 @@ def unload_modules(self, *modules: typing.Union[str, pathlib.Path]) -> Self: return self def _reload_module( - self, module_path: typing.Union[str, pathlib.Path], / + self, module_path: str | pathlib.Path, / ) -> collections.Generator[collections.Callable[[], types.ModuleType], types.ModuleType, None]: if isinstance(module_path, str): old_module = self._modules.get(module_path) - load_module: typing.Optional[_ReloadModule] = None + load_module: _ReloadModule | None = None modules_dict: dict[typing.Any, types.ModuleType] = self._modules else: @@ -2709,7 +2678,7 @@ def _reload_module( else: modules_dict[module_path] = module - def reload_modules(self, *modules: typing.Union[str, pathlib.Path]) -> Self: + def reload_modules(self, *modules: str | pathlib.Path) -> Self: # <>. for module_path in modules: if isinstance(module_path, pathlib.Path): @@ -2729,7 +2698,7 @@ def reload_modules(self, *modules: typing.Union[str, pathlib.Path]) -> Self: return self - async def reload_modules_async(self, *modules: typing.Union[str, pathlib.Path]) -> None: + async def reload_modules_async(self, *modules: str | pathlib.Path) -> None: # <>. loop = asyncio.get_running_loop() for module_path in modules: @@ -2759,11 +2728,11 @@ def set_type_dependency(self, type_: type[_T], value: _T, /) -> Self: def get_type_dependency(self, type_: type[_T], /) -> _T: ... @typing.overload - def get_type_dependency(self, type_: type[_T], /, *, default: _DefaultT) -> typing.Union[_T, _DefaultT]: ... + def get_type_dependency(self, type_: type[_T], /, *, default: _DefaultT) -> _T | _DefaultT: ... def get_type_dependency( - self, type_: type[_T], /, *, default: typing.Union[_DefaultT, tanjun.NoDefault] = tanjun.NO_DEFAULT - ) -> typing.Union[_T, _DefaultT]: + self, type_: type[_T], /, *, default: _DefaultT | tanjun.NoDefault = tanjun.NO_DEFAULT + ) -> _T | _DefaultT: # <>. if default is tanjun.NO_DEFAULT: return self._injector.get_type_dependency(type_) @@ -2782,9 +2751,7 @@ def set_callback_override( self._injector.set_callback_override(callback, override) return self - def get_callback_override( - self, callback: alluka.abc.CallbackSig[_T], / - ) -> typing.Optional[alluka.abc.CallbackSig[_T]]: + def get_callback_override(self, callback: alluka.abc.CallbackSig[_T], /) -> alluka.abc.CallbackSig[_T] | None: # <>. return self._injector.get_callback_override(callback) @@ -2811,7 +2778,7 @@ async def on_message_create_event(self, event: hikari.MessageCreateEvent, /) -> return ctx.set_content(ctx.content.lstrip()[len(prefix) :].lstrip()).set_triggering_prefix(prefix) - hooks: typing.Optional[set[tanjun.MessageHooks]] = None + hooks: set[tanjun.MessageHooks] | None = None if self._hooks and self._message_hooks: hooks = {self._hooks, self._message_hooks} @@ -2836,8 +2803,8 @@ async def on_message_create_event(self, event: hikari.MessageCreateEvent, /) -> await self.dispatch_client_callback(ClientCallbackNames.MESSAGE_COMMAND_NOT_FOUND, ctx) - def _get_slash_hooks(self) -> typing.Optional[set[tanjun.SlashHooks]]: - hooks: typing.Optional[set[tanjun.SlashHooks]] = None + def _get_slash_hooks(self) -> set[tanjun.SlashHooks] | None: + hooks: set[tanjun.SlashHooks] | None = None if self._hooks and self._slash_hooks: hooks = {self._hooks, self._slash_hooks} @@ -2849,8 +2816,8 @@ def _get_slash_hooks(self) -> typing.Optional[set[tanjun.SlashHooks]]: return hooks - def _get_menu_hooks(self) -> typing.Optional[set[tanjun.MenuHooks]]: - hooks: typing.Optional[set[tanjun.MenuHooks]] = None + def _get_menu_hooks(self) -> set[tanjun.MenuHooks] | None: + hooks: set[tanjun.MenuHooks] | None = None if self._hooks and self._menu_hooks: hooks = {self._hooks, self._menu_hooks} @@ -2895,14 +2862,14 @@ async def on_gateway_command_create(self, interaction: hikari.CommandInteraction The interaction to execute a command based on. """ if interaction.command_type is hikari.CommandType.SLASH: - ctx: typing.Union[context.MenuContext, context.SlashContext] = self._make_slash_context( + ctx: context.MenuContext | context.SlashContext = self._make_slash_context( client=self, interaction=interaction, register_task=self._add_task, on_not_found=self._on_slash_not_found, default_to_ephemeral=self._defaults_to_ephemeral, ) - hooks: typing.Union[set[tanjun.MenuHooks], set[tanjun.SlashHooks], None] = self._get_slash_hooks() + hooks: set[tanjun.MenuHooks] | set[tanjun.SlashHooks] | None = self._get_slash_hooks() elif interaction.command_type in _MENU_TYPES: ctx = self._make_menu_context( @@ -3007,9 +2974,11 @@ async def on_autocomplete_interaction_request( async def on_command_interaction_request( self, interaction: hikari.CommandInteraction, / - ) -> typing.Union[ - hikari.api.InteractionMessageBuilder, hikari.api.InteractionDeferredBuilder, hikari.api.InteractionModalBuilder - ]: + ) -> ( + hikari.api.InteractionMessageBuilder + | hikari.api.InteractionDeferredBuilder + | hikari.api.InteractionModalBuilder + ): """Execute an app command based on received REST requests. Parameters @@ -3026,7 +2995,7 @@ async def on_command_interaction_request( future: asyncio.Future[_AppCmdResponse] = loop.create_future() if interaction.command_type is hikari.CommandType.SLASH: - ctx: typing.Union[context.MenuContext, context.SlashContext] = self._make_slash_context( + ctx: context.MenuContext | context.SlashContext = self._make_slash_context( client=self, interaction=interaction, register_task=self._add_task, @@ -3034,7 +3003,7 @@ async def on_command_interaction_request( default_to_ephemeral=self._defaults_to_ephemeral, future=future, ) - hooks: typing.Union[set[tanjun.MenuHooks], set[tanjun.SlashHooks], None] = self._get_slash_hooks() + hooks: set[tanjun.MenuHooks] | set[tanjun.SlashHooks] | None = self._get_slash_hooks() elif interaction.command_type in _MENU_TYPES: ctx = self._make_menu_context( @@ -3092,7 +3061,7 @@ async def on_command_interaction_request( async def _mark_not_found_request( self, - ctx: typing.Union[context.SlashContext, context.MenuContext], + ctx: context.SlashContext | context.MenuContext, loop: asyncio.AbstractEventLoop, future: asyncio.Future[_AppCmdResponse], /, @@ -3103,7 +3072,7 @@ async def _mark_not_found_request( return await future -async def _mark_not_found_event(ctx: typing.Union[context.SlashContext, context.MenuContext], /) -> None: +async def _mark_not_found_event(ctx: context.SlashContext | context.MenuContext, /) -> None: try: await ctx.mark_not_found() @@ -3111,7 +3080,7 @@ async def _mark_not_found_event(ctx: typing.Union[context.SlashContext, context. ctx.cancel_defer() -def _scan_directory(path: pathlib.Path, namespace: typing.Optional[str], /) -> list[typing.Union[pathlib.Path, str]]: +def _scan_directory(path: pathlib.Path, namespace: str | None, /) -> list[pathlib.Path | str]: if namespace: return [namespace + "." + path.name.removesuffix(".py") for path in path.glob("*.py") if path.is_file()] @@ -3127,9 +3096,7 @@ def _normalize_path(path: pathlib.Path, /) -> pathlib.Path: return path.resolve() -def _get_loaders( - module: types.ModuleType, module_path: typing.Union[str, pathlib.Path], / -) -> list[tanjun.ClientLoader]: +def _get_loaders(module: types.ModuleType, module_path: str | pathlib.Path, /) -> list[tanjun.ClientLoader]: exported = getattr(module, "__all__", None) if exported is not None and isinstance(exported, collections.Iterable): _LOGGER.debug("Scanning %s module based on its declared __all__)", module_path) @@ -3172,10 +3139,7 @@ def __enter__(self) -> None: pass def __exit__( - self, - exc_type: typing.Optional[type[BaseException]], - exc: typing.Optional[BaseException], - exc_tb: typing.Optional[types.TracebackType], + self, exc_type: type[BaseException] | None, exc: BaseException | None, exc_tb: types.TracebackType | None ) -> None: if ( exc @@ -3214,7 +3178,7 @@ def _try_unsubscribe( class _LoadModule: __slots__ = ("path",) - path: typing.Union[str, pathlib.Path] + path: str | pathlib.Path def __call__(self) -> types.ModuleType: return importlib.import_module(self.path) if isinstance(self.path, str) else _get_path_module(self.path) @@ -3224,7 +3188,7 @@ def __call__(self) -> types.ModuleType: class _ReloadModule: __slots__ = ("path",) - path: typing.Union[types.ModuleType, pathlib.Path] + path: types.ModuleType | pathlib.Path def __call__(self) -> types.ModuleType: return _get_path_module(self.path) if isinstance(self.path, pathlib.Path) else importlib.reload(self.path) diff --git a/tanjun/commands/base.py b/tanjun/commands/base.py index faffca795..e9a28f23f 100644 --- a/tanjun/commands/base.py +++ b/tanjun/commands/base.py @@ -41,8 +41,7 @@ if typing.TYPE_CHECKING: from collections import abc as collections - - from typing_extensions import Self + from typing import Self _CheckSigT = typing.TypeVar("_CheckSigT", bound=tanjun.AnyCheckSig) @@ -57,8 +56,8 @@ class PartialCommand(tanjun.ExecutableCommand[_ContextT], components.AbstractCom def __init__(self) -> None: self._checks: list[tanjun.CheckSig[_ContextT]] = [] - self._component: typing.Optional[tanjun.Component] = None - self._hooks: typing.Optional[tanjun.Hooks[_ContextT]] = None + self._component: tanjun.Component | None = None + self._hooks: tanjun.Hooks[_ContextT] | None = None self._metadata: dict[typing.Any, typing.Any] = {} @property @@ -67,12 +66,12 @@ def checks(self) -> collections.Collection[tanjun.CheckSig[_ContextT]]: return self._checks.copy() @property - def component(self) -> typing.Optional[tanjun.Component]: + def component(self) -> tanjun.Component | None: # <>. return self._component @property - def hooks(self) -> typing.Optional[tanjun.Hooks[_ContextT]]: + def hooks(self) -> tanjun.Hooks[_ContextT] | None: # <>. return self._hooks @@ -89,7 +88,7 @@ def copy(self) -> Self: inst._metadata = self._metadata.copy() return inst - def set_hooks(self, hooks: typing.Optional[tanjun.Hooks[_ContextT]], /) -> Self: + def set_hooks(self, hooks: tanjun.Hooks[_ContextT] | None, /) -> Self: # <>. self._hooks = hooks return self diff --git a/tanjun/commands/menu.py b/tanjun/commands/menu.py index a6a37c0c0..33f985817 100644 --- a/tanjun/commands/menu.py +++ b/tanjun/commands/menu.py @@ -47,8 +47,7 @@ if typing.TYPE_CHECKING: from collections import abc as collections - - from typing_extensions import Self + from typing import Self _AnyCallbackSigT = typing.TypeVar( "_AnyCallbackSigT", bound=collections.Callable[..., collections.Coroutine[typing.Any, typing.Any, None]] @@ -56,12 +55,12 @@ _MessageCallbackSigT = typing.TypeVar("_MessageCallbackSigT", bound=tanjun.MenuCallbackSig[hikari.Message]) _UserCallbackSigT = typing.TypeVar("_UserCallbackSigT", bound=tanjun.MenuCallbackSig[hikari.InteractionMember]) - _AnyCommandT = typing.Union[ - tanjun.MenuCommand[_AnyCallbackSigT, typing.Any], - tanjun.MessageCommand[_AnyCallbackSigT], - tanjun.SlashCommand[_AnyCallbackSigT], - ] - _CallbackishT = typing.Union[_AnyCallbackSigT, _AnyCommandT[_AnyCallbackSigT]] + _AnyCommandT = ( + tanjun.MenuCommand[_AnyCallbackSigT, typing.Any] + | tanjun.MessageCommand[_AnyCallbackSigT] + | tanjun.SlashCommand[_AnyCallbackSigT] + ) + _CallbackishT = _AnyCallbackSigT | _AnyCommandT[_AnyCallbackSigT] _AnyMenuCallbackSigT = typing.TypeVar("_AnyMenuCallbackSigT", bound=tanjun.MenuCallbackSig[typing.Any]) _MenuTypeT = typing.TypeVar( @@ -85,13 +84,13 @@ def __call__( def as_message_menu( - name: typing.Union[str, collections.Mapping[str, str]], + name: str | collections.Mapping[str, str], /, *, always_defer: bool = False, - default_member_permissions: typing.Union[hikari.Permissions, int, None] = None, - default_to_ephemeral: typing.Optional[bool] = None, - dm_enabled: typing.Optional[bool] = None, + default_member_permissions: hikari.Permissions | int | None = None, + default_to_ephemeral: bool | None = None, + dm_enabled: bool | None = None, is_global: bool = True, nsfw: bool = False, ) -> _AsMsgResultProto: @@ -210,13 +209,13 @@ def __call__( def as_user_menu( - name: typing.Union[str, collections.Mapping[str, str]], + name: str | collections.Mapping[str, str], /, *, always_defer: bool = False, - default_member_permissions: typing.Union[hikari.Permissions, int, None] = None, - default_to_ephemeral: typing.Optional[bool] = None, - dm_enabled: typing.Optional[bool] = None, + default_member_permissions: hikari.Permissions | int | None = None, + default_to_ephemeral: bool | None = None, + dm_enabled: bool | None = None, is_global: bool = True, nsfw: bool = False, ) -> _AsUserResultProto: @@ -349,16 +348,16 @@ def __init__( self: MenuCommand[_UserCallbackSigT, typing.Literal[hikari.CommandType.USER]], callback: _UserCallbackSigT, type_: typing.Literal[hikari.CommandType.USER], - name: typing.Union[str, collections.Mapping[str, str]], + name: str | collections.Mapping[str, str], /, *, always_defer: bool = False, - default_member_permissions: typing.Union[hikari.Permissions, int, None] = None, - default_to_ephemeral: typing.Optional[bool] = None, - dm_enabled: typing.Optional[bool] = None, + default_member_permissions: hikari.Permissions | int | None = None, + default_to_ephemeral: bool | None = None, + dm_enabled: bool | None = None, is_global: bool = True, nsfw: bool = False, - _wrapped_command: typing.Optional[tanjun.ExecutableCommand[typing.Any]] = None, + _wrapped_command: tanjun.ExecutableCommand[typing.Any] | None = None, ) -> None: ... # While this extra overload may seem redundant/unnecessary, MyPy cannot understand @@ -368,16 +367,16 @@ def __init__( self: MenuCommand[_UserCallbackSigT, typing.Literal[hikari.CommandType.USER]], callback: _AnyCommandT[_UserCallbackSigT], type_: typing.Literal[hikari.CommandType.USER], - name: typing.Union[str, collections.Mapping[str, str]], + name: str | collections.Mapping[str, str], /, *, always_defer: bool = False, - default_member_permissions: typing.Union[hikari.Permissions, int, None] = None, - default_to_ephemeral: typing.Optional[bool] = None, - dm_enabled: typing.Optional[bool] = None, + default_member_permissions: hikari.Permissions | int | None = None, + default_to_ephemeral: bool | None = None, + dm_enabled: bool | None = None, is_global: bool = True, nsfw: bool = False, - _wrapped_command: typing.Optional[tanjun.ExecutableCommand[typing.Any]] = None, + _wrapped_command: tanjun.ExecutableCommand[typing.Any] | None = None, ) -> None: ... @typing.overload @@ -385,16 +384,16 @@ def __init__( self: MenuCommand[_MessageCallbackSigT, typing.Literal[hikari.CommandType.MESSAGE]], callback: _MessageCallbackSigT, type_: typing.Literal[hikari.CommandType.MESSAGE], - name: typing.Union[str, collections.Mapping[str, str]], + name: str | collections.Mapping[str, str], /, *, always_defer: bool = False, - default_member_permissions: typing.Union[hikari.Permissions, int, None] = None, - default_to_ephemeral: typing.Optional[bool] = None, - dm_enabled: typing.Optional[bool] = None, + default_member_permissions: hikari.Permissions | int | None = None, + default_to_ephemeral: bool | None = None, + dm_enabled: bool | None = None, is_global: bool = True, nsfw: bool = False, - _wrapped_command: typing.Optional[tanjun.ExecutableCommand[typing.Any]] = None, + _wrapped_command: tanjun.ExecutableCommand[typing.Any] | None = None, ) -> None: ... # While this extra overload may seem redundant/unnecessary, MyPy cannot understand @@ -404,35 +403,38 @@ def __init__( self: MenuCommand[_MessageCallbackSigT, typing.Literal[hikari.CommandType.MESSAGE]], callback: _AnyCommandT[_MessageCallbackSigT], type_: typing.Literal[hikari.CommandType.MESSAGE], - name: typing.Union[str, collections.Mapping[str, str]], + name: str | collections.Mapping[str, str], /, *, always_defer: bool = False, - default_member_permissions: typing.Union[hikari.Permissions, int, None] = None, - default_to_ephemeral: typing.Optional[bool] = None, - dm_enabled: typing.Optional[bool] = None, + default_member_permissions: hikari.Permissions | int | None = None, + default_to_ephemeral: bool | None = None, + dm_enabled: bool | None = None, is_global: bool = True, nsfw: bool = False, - _wrapped_command: typing.Optional[tanjun.ExecutableCommand[typing.Any]] = None, + _wrapped_command: tanjun.ExecutableCommand[typing.Any] | None = None, ) -> None: ... def __init__( self, - callback: typing.Union[ - _UserCallbackSigT, _AnyCommandT[_UserCallbackSigT], _MessageCallbackSigT, _AnyCommandT[_MessageCallbackSigT] - ], + callback: ( + _UserCallbackSigT + | _AnyCommandT[_UserCallbackSigT] + | _MessageCallbackSigT + | _AnyCommandT[_MessageCallbackSigT] + ), # TODO: should be _MenuTypeT but pyright broke type_: typing.Any, - name: typing.Union[str, collections.Mapping[str, str]], + name: str | collections.Mapping[str, str], /, *, always_defer: bool = False, - default_member_permissions: typing.Union[hikari.Permissions, int, None] = None, - default_to_ephemeral: typing.Optional[bool] = None, - dm_enabled: typing.Optional[bool] = None, + default_member_permissions: hikari.Permissions | int | None = None, + default_to_ephemeral: bool | None = None, + dm_enabled: bool | None = None, is_global: bool = True, nsfw: bool = False, - _wrapped_command: typing.Optional[tanjun.ExecutableCommand[typing.Any]] = None, + _wrapped_command: tanjun.ExecutableCommand[typing.Any] | None = None, ) -> None: """Initialise a user or message menu command. @@ -529,8 +531,8 @@ def __init__( self._is_global = is_global self._is_nsfw = nsfw self._names = names - self._parent: typing.Optional[tanjun.SlashCommandGroup] = None - self._tracked_command: typing.Optional[hikari.ContextMenuCommand] = None + self._parent: tanjun.SlashCommandGroup | None = None + self._tracked_command: hikari.ContextMenuCommand | None = None self._type: _MenuTypeT = type_ # MyPy bug causes this to need an explicit annotation. self._wrapped_command = _wrapped_command @@ -548,17 +550,17 @@ def callback(self) -> _AnyMenuCallbackSigT: return self._callback @property - def default_member_permissions(self) -> typing.Optional[hikari.Permissions]: + def default_member_permissions(self) -> hikari.Permissions | None: # <>. return self._default_member_permissions @property - def defaults_to_ephemeral(self) -> typing.Optional[bool]: + def defaults_to_ephemeral(self) -> bool | None: # <>. return self._defaults_to_ephemeral @property - def is_dm_enabled(self) -> typing.Optional[bool]: + def is_dm_enabled(self) -> bool | None: return self._is_dm_enabled @property @@ -567,7 +569,7 @@ def is_global(self) -> bool: return self._is_global @property - def is_nsfw(self) -> typing.Optional[bool]: + def is_nsfw(self) -> bool | None: # <>. return self._is_nsfw @@ -581,12 +583,12 @@ def name_localisations(self) -> collections.Mapping[str, str]: return self._names.localised_values.copy() @property - def tracked_command(self) -> typing.Optional[hikari.ContextMenuCommand]: + def tracked_command(self) -> hikari.ContextMenuCommand | None: # <>. return self._tracked_command @property - def tracked_command_id(self) -> typing.Optional[hikari.Snowflake]: + def tracked_command_id(self) -> hikari.Snowflake | None: # <>. return self._tracked_command.id if self._tracked_command else None @@ -596,11 +598,11 @@ def type(self) -> _MenuTypeT: return self._type @property - def wrapped_command(self) -> typing.Optional[tanjun.ExecutableCommand[typing.Any]]: + def wrapped_command(self) -> tanjun.ExecutableCommand[typing.Any] | None: """The command object this wraps, if any.""" return self._wrapped_command - def build(self, *, component: typing.Optional[tanjun.Component] = None) -> hikari.api.ContextMenuCommandBuilder: + def build(self, *, component: tanjun.Component | None = None) -> hikari.api.ContextMenuCommandBuilder: # <>. builder = hikari.impl.ContextMenuCommandBuilder( type=self._type, @@ -630,7 +632,7 @@ def set_tracked_command(self, command: hikari.PartialCommand, /) -> Self: self._tracked_command = command return self - def set_ephemeral_default(self, state: typing.Optional[bool], /) -> Self: + def set_ephemeral_default(self, state: bool | None, /) -> Self: """Set whether this command's responses should default to ephemeral. Parameters @@ -658,14 +660,14 @@ async def check_context(self, ctx: tanjun.MenuContext, /) -> bool: ctx.set_command(None) return result - def copy(self, *, parent: typing.Optional[tanjun.SlashCommandGroup] = None) -> Self: + def copy(self, *, parent: tanjun.SlashCommandGroup | None = None) -> Self: # <>. inst = super().copy() inst._parent = parent return inst async def execute( - self, ctx: tanjun.MenuContext, /, *, hooks: typing.Optional[collections.MutableSet[tanjun.MenuHooks]] = None + self, ctx: tanjun.MenuContext, /, *, hooks: collections.MutableSet[tanjun.MenuHooks] | None = None ) -> None: # <>. if self._always_defer and not ctx.has_been_deferred and not ctx.has_responded: @@ -677,7 +679,7 @@ async def execute( await own_hooks.trigger_pre_execution(ctx, hooks=hooks) if self._type is hikari.CommandType.USER: - value: typing.Union[hikari.Message, hikari.User] = ctx.resolve_to_user() + value: hikari.Message | hikari.User = ctx.resolve_to_user() else: value = ctx.resolve_to_message() diff --git a/tanjun/commands/message.py b/tanjun/commands/message.py index c77d28b7b..1b6fcc642 100644 --- a/tanjun/commands/message.py +++ b/tanjun/commands/message.py @@ -45,16 +45,17 @@ if typing.TYPE_CHECKING: from collections import abc as collections - - from typing_extensions import Self + from typing import Self _AnyMessageCommandT = typing.TypeVar("_AnyMessageCommandT", bound=tanjun.MessageCommand[typing.Any]) _AnyCallbackSigT = typing.TypeVar("_AnyCallbackSigT", bound=collections.Callable[..., typing.Any]) - _AnyCommandT = typing.Union[ - tanjun.MenuCommand[_AnyCallbackSigT, typing.Any], - tanjun.MessageCommand[_AnyCallbackSigT], - tanjun.SlashCommand[_AnyCallbackSigT], - ] + _AnyCommandT = ( + tanjun.MenuCommand[_AnyCallbackSigT, typing.Any] + | tanjun.MessageCommand[_AnyCallbackSigT] + | tanjun.SlashCommand[_AnyCallbackSigT] + ) + + # Pyright bug doesn't accept Var = Class | Class as a type _CallbackishT = typing.Union[_AnyCommandT["_MessageCallbackSigT"], "_MessageCallbackSigT"] _OtherCallbackSigT = typing.TypeVar("_OtherCallbackSigT", bound=tanjun.MessageCallbackSig) @@ -186,7 +187,7 @@ def __init__( /, *names: str, validate_arg_keys: bool = True, - _wrapped_command: typing.Optional[tanjun.ExecutableCommand[typing.Any]] = None, + _wrapped_command: tanjun.ExecutableCommand[typing.Any] | None = None, ) -> None: ... @typing.overload @@ -197,7 +198,7 @@ def __init__( /, *names: str, validate_arg_keys: bool = True, - _wrapped_command: typing.Optional[tanjun.ExecutableCommand[typing.Any]] = None, + _wrapped_command: tanjun.ExecutableCommand[typing.Any] | None = None, ) -> None: ... def __init__( @@ -207,7 +208,7 @@ def __init__( /, *names: str, validate_arg_keys: bool = True, - _wrapped_command: typing.Optional[tanjun.ExecutableCommand[typing.Any]] = None, + _wrapped_command: tanjun.ExecutableCommand[typing.Any] | None = None, ) -> None: """Initialise a message command. @@ -234,8 +235,8 @@ def __init__( self._arg_names = _internal.get_kwargs(callback) if validate_arg_keys else None self._callback: _MessageCallbackSigT = callback self._names = list(dict.fromkeys((name, *names))) - self._parent: typing.Optional[tanjun.MessageCommandGroup[typing.Any]] = None - self._parser: typing.Optional[tanjun.MessageParser] = None + self._parent: tanjun.MessageCommandGroup[typing.Any] | None = None + self._parser: tanjun.MessageParser | None = None self._wrapped_command = _wrapped_command def __repr__(self) -> str: @@ -260,17 +261,17 @@ def names(self) -> collections.Collection[str]: return self._names.copy() @property - def parent(self) -> typing.Optional[tanjun.MessageCommandGroup[typing.Any]]: + def parent(self) -> tanjun.MessageCommandGroup[typing.Any] | None: # <>. return self._parent @property - def parser(self) -> typing.Optional[tanjun.MessageParser]: + def parser(self) -> tanjun.MessageParser | None: # <>. return self._parser @property - def wrapped_command(self) -> typing.Optional[tanjun.ExecutableCommand[typing.Any]]: + def wrapped_command(self) -> tanjun.ExecutableCommand[typing.Any] | None: """The command object this wraps, if any.""" return self._wrapped_command @@ -290,7 +291,7 @@ def bind_component(self, component: tanjun.Component, /) -> Self: return self - def copy(self, *, parent: typing.Optional[tanjun.MessageCommandGroup[typing.Any]] = None) -> Self: + def copy(self, *, parent: tanjun.MessageCommandGroup[typing.Any] | None = None) -> Self: # <>. inst = super().copy() inst._callback = copy.copy(self._callback) @@ -299,12 +300,12 @@ def copy(self, *, parent: typing.Optional[tanjun.MessageCommandGroup[typing.Any] inst._parser = self._parser.copy() if self._parser else None return inst - def set_parent(self, parent: typing.Optional[tanjun.MessageCommandGroup[typing.Any]], /) -> Self: + def set_parent(self, parent: tanjun.MessageCommandGroup[typing.Any] | None, /) -> Self: # <>. self._parent = parent return self - def set_parser(self, parser: typing.Optional[tanjun.MessageParser], /) -> Self: + def set_parser(self, parser: tanjun.MessageParser | None, /) -> Self: # <>. if parser and self._arg_names is not None: try: @@ -325,11 +326,7 @@ async def check_context(self, ctx: tanjun.MessageContext, /) -> bool: return result async def execute( - self, - ctx: tanjun.MessageContext, - /, - *, - hooks: typing.Optional[collections.MutableSet[tanjun.MessageHooks]] = None, + self, ctx: tanjun.MessageContext, /, *, hooks: collections.MutableSet[tanjun.MessageHooks] | None = None ) -> None: # <>. ctx = ctx.set_command(self) @@ -386,7 +383,7 @@ def __init__( *names: str, strict: bool = False, validate_arg_keys: bool = True, - _wrapped_command: typing.Optional[tanjun.ExecutableCommand[typing.Any]] = None, + _wrapped_command: tanjun.ExecutableCommand[typing.Any] | None = None, ) -> None: ... @typing.overload @@ -398,7 +395,7 @@ def __init__( *names: str, strict: bool = False, validate_arg_keys: bool = True, - _wrapped_command: typing.Optional[tanjun.ExecutableCommand[typing.Any]] = None, + _wrapped_command: tanjun.ExecutableCommand[typing.Any] | None = None, ) -> None: ... def __init__( @@ -409,7 +406,7 @@ def __init__( *names: str, strict: bool = False, validate_arg_keys: bool = True, - _wrapped_command: typing.Optional[tanjun.ExecutableCommand[typing.Any]] = None, + _wrapped_command: tanjun.ExecutableCommand[typing.Any] | None = None, ) -> None: """Initialise a message command group. @@ -448,7 +445,7 @@ def commands(self) -> collections.Collection[tanjun.MessageCommand[typing.Any]]: def is_strict(self) -> bool: return self._commands.is_strict - def copy(self, *, parent: typing.Optional[tanjun.MessageCommandGroup[typing.Any]] = None) -> Self: + def copy(self, *, parent: tanjun.MessageCommandGroup[typing.Any] | None = None) -> Self: # <>. inst = super().copy(parent=parent) inst._commands = self._commands.copy(parent=self) @@ -503,7 +500,7 @@ def as_sub_command( """ def decorator( - callback: typing.Union[_OtherCallbackSigT, _AnyCommandT[_OtherCallbackSigT]], / + callback: _OtherCallbackSigT | _AnyCommandT[_OtherCallbackSigT], / ) -> MessageCommand[_OtherCallbackSigT]: cmd = as_message_command(name, *names, validate_arg_keys=validate_arg_keys)(callback) self.add_command(cmd) @@ -579,11 +576,7 @@ def find_command( return self._commands.find(content, case_sensntive) async def execute( - self, - ctx: tanjun.MessageContext, - /, - *, - hooks: typing.Optional[collections.MutableSet[tanjun.MessageHooks]] = None, + self, ctx: tanjun.MessageContext, /, *, hooks: collections.MutableSet[tanjun.MessageHooks] | None = None ) -> None: # <>. if ctx.message.content is None: diff --git a/tanjun/commands/slash.py b/tanjun/commands/slash.py index 3e8616f14..2c20462d0 100644 --- a/tanjun/commands/slash.py +++ b/tanjun/commands/slash.py @@ -69,18 +69,22 @@ from . import base if typing.TYPE_CHECKING: + from typing import Self + from hikari.api import special_endpoints as special_endpoints_api - from typing_extensions import Self _AnyCallbackSigT = typing.TypeVar("_AnyCallbackSigT", bound=collections.Callable[..., typing.Any]) _AnyBaseSlashCommandT = typing.TypeVar("_AnyBaseSlashCommandT", bound=tanjun.BaseSlashCommand) _SlashCommandT = typing.TypeVar("_SlashCommandT", bound="SlashCommand[typing.Any]") - _AnyCommandT = typing.Union[ - tanjun.MenuCommand[_AnyCallbackSigT, typing.Any], - tanjun.MessageCommand[_AnyCallbackSigT], - tanjun.SlashCommand[_AnyCallbackSigT], - ] + _AnyCommandT = ( + tanjun.MenuCommand[_AnyCallbackSigT, typing.Any] + | tanjun.MessageCommand[_AnyCallbackSigT] + | tanjun.SlashCommand[_AnyCallbackSigT] + ) + + # Pyright bug doesn't accept Var = Class | Class as a type _AnyConverterSig = typing.Union["ConverterSig[float]", "ConverterSig[int]", "ConverterSig[str]"] + # Pyright bug doesn't accept Var = Class | Class as a type _CallbackishT = typing.Union["_SlashCallbackSigT", _AnyCommandT["_SlashCallbackSigT"]] _IntAutocompleteSigT = typing.TypeVar("_IntAutocompleteSigT", bound=tanjun.AutocompleteSig[int]) @@ -91,23 +95,17 @@ _SlashCallbackSigT = typing.TypeVar("_SlashCallbackSigT", bound=tanjun.SlashCallbackSig) _ConvertT = typing.TypeVar("_ConvertT", int, float, str) -# 3.9 and 3.10 just can't handle ending Concatenate with ... so we lie about this at runtime. -if typing.TYPE_CHECKING: - ConverterSig = collections.Callable[ - typing_extensions.Concatenate[_ConvertT, ...], - typing.Union[collections.Coroutine[typing.Any, typing.Any, typing.Any], typing.Any], - ] - """Type hint of a slash command option converter. - - This represents the signatures `def (int | float | str, ...) -> Any` and - `async def (int | float | str, ...) -> None` where dependency injection is - supported. - """ -else: - import types +ConverterSig = collections.Callable[ + typing.Concatenate[_ConvertT, ...], collections.Coroutine[typing.Any, typing.Any, typing.Any] | typing.Any +] +"""Type hint of a slash command option converter. + +This represents the signatures `def (int | float | str, ...) -> Any` and +`async def (int | float | str, ...) -> None` where dependency injection is +supported. +""" - ConverterSig = types.GenericAlias(collections.Callable[..., typing.Any], (_ConvertT,)) _EMPTY_DICT: typing.Final[dict[typing.Any, typing.Any]] = {} _EMPTY_HOOKS: typing.Final[hooks_.Hooks[typing.Any]] = hooks_.Hooks() @@ -151,13 +149,13 @@ def _validate_name(name: str, /) -> bool: def slash_command_group( - name: typing.Union[str, collections.Mapping[str, str]], - description: typing.Union[str, collections.Mapping[str, str]], + name: str | collections.Mapping[str, str], + description: str | collections.Mapping[str, str], /, *, - default_member_permissions: typing.Union[hikari.Permissions, int, None] = None, - default_to_ephemeral: typing.Optional[bool] = None, - dm_enabled: typing.Optional[bool] = None, + default_member_permissions: hikari.Permissions | int | None = None, + default_to_ephemeral: bool | None = None, + dm_enabled: bool | None = None, nsfw: bool = False, is_global: bool = True, ) -> SlashCommandGroup: @@ -265,14 +263,14 @@ def __call__(self, _: _AnyCommandT[_SlashCallbackSigT], /) -> SlashCommand[_Slas def as_slash_command( - name: typing.Union[str, collections.Mapping[str, str]], - description: typing.Union[str, collections.Mapping[str, str]], + name: str | collections.Mapping[str, str], + description: str | collections.Mapping[str, str], /, *, always_defer: bool = False, - default_member_permissions: typing.Union[hikari.Permissions, int, None] = None, - default_to_ephemeral: typing.Optional[bool] = None, - dm_enabled: typing.Optional[bool] = None, + default_member_permissions: hikari.Permissions | int | None = None, + default_to_ephemeral: bool | None = None, + dm_enabled: bool | None = None, is_global: bool = True, nsfw: bool = False, sort_options: bool = True, @@ -402,12 +400,12 @@ def decorator(callback: _CallbackishT[_SlashCallbackSigT], /) -> SlashCommand[_S def with_attachment_slash_option( - name: typing.Union[str, collections.Mapping[str, str]], - description: typing.Union[str, collections.Mapping[str, str]], + name: str | collections.Mapping[str, str], + description: str | collections.Mapping[str, str], /, *, default: typing.Any = tanjun.NO_DEFAULT, - key: typing.Optional[str] = None, + key: str | None = None, pass_as_kwarg: bool = True, ) -> collections.Callable[[_SlashCommandT], _SlashCommandT]: """Add an attachment option to a slash command. @@ -435,19 +433,19 @@ async def command(self, ctx: tanjun.abc.SlashContext, name: hikari.Attachment) - def with_str_slash_option( - name: typing.Union[str, collections.Mapping[str, str]], - description: typing.Union[str, collections.Mapping[str, str]], + name: str | collections.Mapping[str, str], + description: str | collections.Mapping[str, str], /, *, - autocomplete: typing.Optional[tanjun.AutocompleteSig[str]] = None, - choices: typing.Union[ - collections.Mapping[str, str], collections.Sequence[str], collections.Sequence[hikari.CommandChoice], None - ] = None, - converters: typing.Union[collections.Sequence[ConverterSig[str]], ConverterSig[str]] = (), + autocomplete: tanjun.AutocompleteSig[str] | None = None, + choices: ( + collections.Mapping[str, str] | collections.Sequence[str] | collections.Sequence[hikari.CommandChoice] | None + ) = None, + converters: collections.Sequence[ConverterSig[str]] | ConverterSig[str] = (), default: typing.Any = tanjun.NO_DEFAULT, - key: typing.Optional[str] = None, - min_length: typing.Optional[int] = None, - max_length: typing.Optional[int] = None, + key: str | None = None, + min_length: int | None = None, + max_length: int | None = None, pass_as_kwarg: bool = True, ) -> collections.Callable[[_SlashCommandT], _SlashCommandT]: """Add a string option to a slash command. @@ -485,17 +483,17 @@ async def command(self, ctx: tanjun.abc.SlashContext, name: str) -> None: def with_int_slash_option( - name: typing.Union[str, collections.Mapping[str, str]], - description: typing.Union[str, collections.Mapping[str, str]], + name: str | collections.Mapping[str, str], + description: str | collections.Mapping[str, str], /, *, - autocomplete: typing.Optional[tanjun.AutocompleteSig[int]] = None, - choices: typing.Union[collections.Mapping[str, int], collections.Sequence[hikari.CommandChoice], None] = None, - converters: typing.Union[collections.Sequence[ConverterSig[int]], ConverterSig[int]] = (), + autocomplete: tanjun.AutocompleteSig[int] | None = None, + choices: collections.Mapping[str, int] | collections.Sequence[hikari.CommandChoice] | None = None, + converters: collections.Sequence[ConverterSig[int]] | ConverterSig[int] = (), default: typing.Any = tanjun.NO_DEFAULT, - key: typing.Optional[str] = None, - min_value: typing.Optional[int] = None, - max_value: typing.Optional[int] = None, + key: str | None = None, + min_value: int | None = None, + max_value: int | None = None, pass_as_kwarg: bool = True, ) -> collections.Callable[[_SlashCommandT], _SlashCommandT]: """Add an integer option to a slash command. @@ -533,18 +531,18 @@ async def command(self, ctx: tanjun.abc.SlashContext, int_value: int) -> None: def with_float_slash_option( - name: typing.Union[str, collections.Mapping[str, str]], - description: typing.Union[str, collections.Mapping[str, str]], + name: str | collections.Mapping[str, str], + description: str | collections.Mapping[str, str], /, *, always_float: bool = True, - autocomplete: typing.Optional[tanjun.AutocompleteSig[float]] = None, - choices: typing.Union[collections.Mapping[str, float], collections.Sequence[hikari.CommandChoice], None] = None, - converters: typing.Union[collections.Sequence[ConverterSig[float]], ConverterSig[float]] = (), + autocomplete: tanjun.AutocompleteSig[float] | None = None, + choices: collections.Mapping[str, float] | collections.Sequence[hikari.CommandChoice] | None = None, + converters: collections.Sequence[ConverterSig[float]] | ConverterSig[float] = (), default: typing.Any = tanjun.NO_DEFAULT, - key: typing.Optional[str] = None, - min_value: typing.Optional[float] = None, - max_value: typing.Optional[float] = None, + key: str | None = None, + min_value: float | None = None, + max_value: float | None = None, pass_as_kwarg: bool = True, ) -> collections.Callable[[_SlashCommandT], _SlashCommandT]: """Add a float option to a slash command. @@ -583,12 +581,12 @@ async def command(self, ctx: tanjun.abc.SlashContext, float_value: float) -> Non def with_bool_slash_option( - name: typing.Union[str, collections.Mapping[str, str]], - description: typing.Union[str, collections.Mapping[str, str]], + name: str | collections.Mapping[str, str], + description: str | collections.Mapping[str, str], /, *, default: typing.Any = tanjun.NO_DEFAULT, - key: typing.Optional[str] = None, + key: str | None = None, pass_as_kwarg: bool = True, ) -> collections.Callable[[_SlashCommandT], _SlashCommandT]: """Add a boolean option to a slash command. @@ -614,12 +612,12 @@ async def command(self, ctx: tanjun.abc.SlashContext, flag: bool) -> None: def with_user_slash_option( - name: typing.Union[str, collections.Mapping[str, str]], - description: typing.Union[str, collections.Mapping[str, str]], + name: str | collections.Mapping[str, str], + description: str | collections.Mapping[str, str], /, *, default: typing.Any = tanjun.NO_DEFAULT, - key: typing.Optional[str] = None, + key: str | None = None, pass_as_kwarg: bool = True, ) -> collections.Callable[[_SlashCommandT], _SlashCommandT]: """Add a user option to a slash command. @@ -651,12 +649,12 @@ async def command(self, ctx: tanjun.abc.SlashContext, user: Union[InteractionMem def with_member_slash_option( - name: typing.Union[str, collections.Mapping[str, str]], - description: typing.Union[str, collections.Mapping[str, str]], + name: str | collections.Mapping[str, str], + description: str | collections.Mapping[str, str], /, *, default: typing.Any = tanjun.NO_DEFAULT, - key: typing.Optional[str] = None, + key: str | None = None, ) -> collections.Callable[[_SlashCommandT], _SlashCommandT]: """Add a member option to a slash command. @@ -685,13 +683,13 @@ async def command(self, ctx: tanjun.abc.SlashContext, member: hikari.Interaction def with_channel_slash_option( - name: typing.Union[str, collections.Mapping[str, str]], - description: typing.Union[str, collections.Mapping[str, str]], + name: str | collections.Mapping[str, str], + description: str | collections.Mapping[str, str], /, *, - types: typing.Optional[collections.Collection[typing.Union[type[hikari.PartialChannel], int]]] = None, + types: collections.Collection[type[hikari.PartialChannel] | int] | None = None, default: typing.Any = tanjun.NO_DEFAULT, - key: typing.Optional[str] = None, + key: str | None = None, pass_as_kwarg: bool = True, ) -> collections.Callable[[_SlashCommandT], _SlashCommandT]: """Add a channel option to a slash command. @@ -723,12 +721,12 @@ async def command(self, ctx: tanjun.abc.SlashContext, channel: hikari.Interactio def with_role_slash_option( - name: typing.Union[str, collections.Mapping[str, str]], - description: typing.Union[str, collections.Mapping[str, str]], + name: str | collections.Mapping[str, str], + description: str | collections.Mapping[str, str], /, *, default: typing.Any = tanjun.NO_DEFAULT, - key: typing.Optional[str] = None, + key: str | None = None, pass_as_kwarg: bool = True, ) -> collections.Callable[[_SlashCommandT], _SlashCommandT]: """Add a role option to a slash command. @@ -754,12 +752,12 @@ async def command(self, ctx: tanjun.abc.SlashContext, role: hikari.Role) -> None def with_mentionable_slash_option( - name: typing.Union[str, collections.Mapping[str, str]], - description: typing.Union[str, collections.Mapping[str, str]], + name: str | collections.Mapping[str, str], + description: str | collections.Mapping[str, str], /, *, default: typing.Any = tanjun.NO_DEFAULT, - key: typing.Optional[str] = None, + key: str | None = None, pass_as_kwarg: bool = True, ) -> collections.Callable[[_SlashCommandT], _SlashCommandT]: """Add a mentionable option to a slash command. @@ -796,9 +794,9 @@ def __init__( *, key: str, name: str, - option_type: typing.Union[hikari.OptionType, int], + option_type: hikari.OptionType | int, always_float: bool = False, - converters: typing.Optional[list[_AnyConverterSig]] = None, + converters: list[_AnyConverterSig] | None = None, only_member: bool = False, default: typing.Any = tanjun.NO_DEFAULT, ) -> None: @@ -864,7 +862,7 @@ def add_option(self, option: hikari.CommandOption) -> Self: self._options_dict[option.name] = option return self - def get_option(self, name: str, /) -> typing.Optional[hikari.CommandOption]: + def get_option(self, name: str, /) -> hikari.CommandOption | None: return self._options_dict.get(name) def sort(self) -> Self: @@ -917,13 +915,13 @@ class BaseSlashCommand(base.PartialCommand[tanjun.SlashContext], tanjun.BaseSlas def __init__( self, - name: typing.Union[str, collections.Mapping[str, str]], - description: typing.Union[str, collections.Mapping[str, str]], + name: str | collections.Mapping[str, str], + description: str | collections.Mapping[str, str], /, *, - default_member_permissions: typing.Union[hikari.Permissions, int, None] = None, - default_to_ephemeral: typing.Optional[bool] = None, - dm_enabled: typing.Optional[bool] = None, + default_member_permissions: hikari.Permissions | int | None = None, + default_to_ephemeral: bool | None = None, + dm_enabled: bool | None = None, is_global: bool = True, nsfw: bool = False, ) -> None: @@ -945,16 +943,16 @@ def __init__( self._is_global = is_global self._is_nsfw = nsfw self._names = names - self._parent: typing.Optional[tanjun.SlashCommandGroup] = None - self._tracked_command: typing.Optional[hikari.SlashCommand] = None + self._parent: tanjun.SlashCommandGroup | None = None + self._tracked_command: hikari.SlashCommand | None = None @property - def default_member_permissions(self) -> typing.Optional[hikari.Permissions]: + def default_member_permissions(self) -> hikari.Permissions | None: # <>. return self._default_member_permissions @property - def defaults_to_ephemeral(self) -> typing.Optional[bool]: + def defaults_to_ephemeral(self) -> bool | None: # <>. return self._defaults_to_ephemeral @@ -968,7 +966,7 @@ def description_localisations(self) -> collections.Mapping[str, str]: return self._descriptions.localised_values.copy() @property - def is_dm_enabled(self) -> typing.Optional[bool]: + def is_dm_enabled(self) -> bool | None: # <>. return self._is_dm_enabled @@ -978,7 +976,7 @@ def is_global(self) -> bool: return self._is_global @property - def is_nsfw(self) -> typing.Optional[bool]: + def is_nsfw(self) -> bool | None: # <>. return self._is_nsfw @@ -992,17 +990,17 @@ def name_localisations(self) -> collections.Mapping[str, str]: return self._names.localised_values.copy() @property - def parent(self) -> typing.Optional[tanjun.SlashCommandGroup]: + def parent(self) -> tanjun.SlashCommandGroup | None: # <>. return self._parent @property - def tracked_command(self) -> typing.Optional[hikari.SlashCommand]: + def tracked_command(self) -> hikari.SlashCommand | None: # <>. return self._tracked_command @property - def tracked_command_id(self) -> typing.Optional[hikari.Snowflake]: + def tracked_command_id(self) -> hikari.Snowflake | None: # <>. return self._tracked_command.id if self._tracked_command else None @@ -1019,7 +1017,7 @@ def set_tracked_command(self, command: hikari.PartialCommand, /) -> Self: self._tracked_command = command return self - def set_ephemeral_default(self, state: typing.Optional[bool], /) -> Self: + def set_ephemeral_default(self, state: bool | None, /) -> Self: """Set whether this command's responses should default to ephemeral. Parameters @@ -1040,7 +1038,7 @@ def set_ephemeral_default(self, state: typing.Optional[bool], /) -> Self: self._defaults_to_ephemeral = state return self - def set_parent(self, parent: typing.Optional[tanjun.SlashCommandGroup], /) -> Self: + def set_parent(self, parent: tanjun.SlashCommandGroup | None, /) -> Self: # <>. self._parent = parent return self @@ -1052,7 +1050,7 @@ async def check_context(self, ctx: tanjun.SlashContext, /) -> bool: ctx.set_command(None) return result - def copy(self, *, parent: typing.Optional[tanjun.SlashCommandGroup] = None) -> Self: + def copy(self, *, parent: tanjun.SlashCommandGroup | None = None) -> Self: # <>. inst = super().copy() inst._parent = parent @@ -1076,13 +1074,13 @@ class SlashCommandGroup(BaseSlashCommand, tanjun.SlashCommandGroup): def __init__( self, - name: typing.Union[str, collections.Mapping[str, str]], - description: typing.Union[str, collections.Mapping[str, str]], + name: str | collections.Mapping[str, str], + description: str | collections.Mapping[str, str], /, *, - default_member_permissions: typing.Union[hikari.Permissions, int, None] = None, - default_to_ephemeral: typing.Optional[bool] = None, - dm_enabled: typing.Optional[bool] = None, + default_member_permissions: hikari.Permissions | int | None = None, + default_to_ephemeral: bool | None = None, + dm_enabled: bool | None = None, is_global: bool = True, nsfw: bool = False, ) -> None: @@ -1156,7 +1154,7 @@ def commands(self) -> collections.Collection[tanjun.BaseSlashCommand]: return self._commands.copy().values() @property - def is_nsfw(self) -> typing.Optional[bool]: + def is_nsfw(self) -> bool | None: # <>. return self._is_nsfw @@ -1176,9 +1174,7 @@ def bind_component(self, component: tanjun.Component, /) -> Self: return self - def build( - self, *, component: typing.Optional[tanjun.Component] = None - ) -> special_endpoints_api.SlashCommandBuilder: + def build(self, *, component: tanjun.Component | None = None) -> special_endpoints_api.SlashCommandBuilder: # <>. builder = _SlashCommandBuilder( name=self._names.default_value, @@ -1222,7 +1218,7 @@ def build( return builder - def copy(self, *, parent: typing.Optional[tanjun.SlashCommandGroup] = None) -> Self: + def copy(self, *, parent: tanjun.SlashCommandGroup | None = None) -> Self: # <>. inst = super().copy(parent=parent) inst._commands = {name: command.copy(parent=inst) for name, command in self._commands.items()} @@ -1259,12 +1255,12 @@ def add_command(self, command: tanjun.BaseSlashCommand, /) -> Self: def as_sub_command( self, - name: typing.Union[str, collections.Mapping[str, str]], - description: typing.Union[str, collections.Mapping[str, str]], + name: str | collections.Mapping[str, str], + description: str | collections.Mapping[str, str], /, *, always_defer: bool = False, - default_to_ephemeral: typing.Optional[bool] = None, + default_to_ephemeral: bool | None = None, sort_options: bool = True, validate_arg_keys: bool = True, ) -> collections.Callable[[_CallbackishT[_SlashCallbackSigT]], SlashCommand[_SlashCallbackSigT]]: @@ -1337,11 +1333,11 @@ def decorator(callback: _CallbackishT[_SlashCallbackSigT], /) -> SlashCommand[_S def make_sub_group( self, - name: typing.Union[str, collections.Mapping[str, str]], - description: typing.Union[str, collections.Mapping[str, str]], + name: str | collections.Mapping[str, str], + description: str | collections.Mapping[str, str], /, *, - default_to_ephemeral: typing.Optional[bool] = None, + default_to_ephemeral: bool | None = None, ) -> SlashCommandGroup: r"""Create a sub-command group in this group. @@ -1417,8 +1413,8 @@ async def execute( ctx: tanjun.SlashContext, /, *, - option: typing.Optional[hikari.CommandInteractionOption] = None, - hooks: typing.Optional[collections.MutableSet[tanjun.SlashHooks]] = None, + option: hikari.CommandInteractionOption | None = None, + hooks: collections.MutableSet[tanjun.SlashHooks] | None = None, ) -> None: # <>. if not option and ctx.interaction.options: @@ -1441,11 +1437,7 @@ async def execute( await ctx.mark_not_found() async def execute_autocomplete( - self, - ctx: tanjun.AutocompleteContext, - /, - *, - option: typing.Optional[hikari.AutocompleteInteractionOption] = None, + self, ctx: tanjun.AutocompleteContext, /, *, option: hikari.AutocompleteInteractionOption | None = None ) -> None: if not option and ctx.interaction.options: option = ctx.interaction.options[0] @@ -1463,7 +1455,7 @@ async def execute_autocomplete( await command.execute_autocomplete(ctx, option=option) -def _assert_in_range(name: str, value: typing.Optional[int], min_value: int, max_value: int, /) -> None: +def _assert_in_range(name: str, value: int | None, min_value: int, max_value: int, /) -> None: if value is None: return @@ -1496,56 +1488,56 @@ class SlashCommand(BaseSlashCommand, tanjun.SlashCommand[_SlashCallbackSigT]): def __init__( self, callback: _SlashCallbackSigT, - name: typing.Union[str, collections.Mapping[str, str]], - description: typing.Union[str, collections.Mapping[str, str]], + name: str | collections.Mapping[str, str], + description: str | collections.Mapping[str, str], /, *, always_defer: bool = False, - default_member_permissions: typing.Union[hikari.Permissions, int, None] = None, - default_to_ephemeral: typing.Optional[bool] = None, - dm_enabled: typing.Optional[bool] = None, + default_member_permissions: hikari.Permissions | int | None = None, + default_to_ephemeral: bool | None = None, + dm_enabled: bool | None = None, is_global: bool = True, nsfw: bool = False, sort_options: bool = True, validate_arg_keys: bool = True, - _wrapped_command: typing.Optional[tanjun.ExecutableCommand[typing.Any]] = None, + _wrapped_command: tanjun.ExecutableCommand[typing.Any] | None = None, ) -> None: ... @typing.overload def __init__( self, callback: _AnyCommandT[_SlashCallbackSigT], - name: typing.Union[str, collections.Mapping[str, str]], - description: typing.Union[str, collections.Mapping[str, str]], + name: str | collections.Mapping[str, str], + description: str | collections.Mapping[str, str], /, *, always_defer: bool = False, - default_member_permissions: typing.Union[hikari.Permissions, int, None] = None, - default_to_ephemeral: typing.Optional[bool] = None, - dm_enabled: typing.Optional[bool] = None, + default_member_permissions: hikari.Permissions | int | None = None, + default_to_ephemeral: bool | None = None, + dm_enabled: bool | None = None, is_global: bool = True, nsfw: bool = False, sort_options: bool = True, validate_arg_keys: bool = True, - _wrapped_command: typing.Optional[tanjun.ExecutableCommand[typing.Any]] = None, + _wrapped_command: tanjun.ExecutableCommand[typing.Any] | None = None, ) -> None: ... def __init__( self, callback: _CallbackishT[_SlashCallbackSigT], - name: typing.Union[str, collections.Mapping[str, str]], - description: typing.Union[str, collections.Mapping[str, str]], + name: str | collections.Mapping[str, str], + description: str | collections.Mapping[str, str], /, *, always_defer: bool = False, - default_member_permissions: typing.Union[hikari.Permissions, int, None] = None, - default_to_ephemeral: typing.Optional[bool] = None, - dm_enabled: typing.Optional[bool] = None, + default_member_permissions: hikari.Permissions | int | None = None, + default_to_ephemeral: bool | None = None, + dm_enabled: bool | None = None, is_global: bool = True, nsfw: bool = False, sort_options: bool = True, validate_arg_keys: bool = True, - _wrapped_command: typing.Optional[tanjun.ExecutableCommand[typing.Any]] = None, + _wrapped_command: tanjun.ExecutableCommand[typing.Any] | None = None, ) -> None: r"""Initialise a slash command. @@ -1646,7 +1638,7 @@ def __init__( sort_options=sort_options, ) self._callback: _SlashCallbackSigT = callback - self._client: typing.Optional[tanjun.Client] = None + self._client: tanjun.Client | None = None self._float_autocompletes: dict[str, tanjun.AutocompleteSig[float]] = {} self._int_autocompletes: dict[str, tanjun.AutocompleteSig[int]] = {} self._str_autocompletes: dict[str, tanjun.AutocompleteSig[str]] = {} @@ -1682,7 +1674,7 @@ def str_autocompletes(self) -> collections.Mapping[str, tanjun.AutocompleteSig[s return self._str_autocompletes.copy() @property - def wrapped_command(self) -> typing.Optional[tanjun.ExecutableCommand[typing.Any]]: + def wrapped_command(self) -> tanjun.ExecutableCommand[typing.Any] | None: """The command object this wraps, if any.""" return self._wrapped_command @@ -1694,9 +1686,7 @@ def bind_client(self, client: tanjun.Client, /) -> Self: return self - def build( - self, *, component: typing.Optional[tanjun.Component] = None - ) -> special_endpoints_api.SlashCommandBuilder: + def build(self, *, component: tanjun.Component | None = None) -> special_endpoints_api.SlashCommandBuilder: # <>. builder = self._builder.sort().copy() @@ -1722,25 +1712,25 @@ def _add_option( self, names: localisation.MaybeLocalised, descriptions: localisation.MaybeLocalised, - type_: typing.Union[hikari.OptionType, int] = hikari.OptionType.STRING, + type_: hikari.OptionType | int = hikari.OptionType.STRING, /, *, always_float: bool = False, autocomplete: bool = False, - channel_types: typing.Optional[collections.Sequence[int]] = None, - choices: typing.Union[ - collections.Mapping[str, typing.Union[str, int, float]], - collections.Sequence[tuple[str, typing.Union[str, int, float]]], - collections.Sequence[hikari.CommandChoice], - None, - ] = None, - converters: typing.Union[collections.Sequence[_AnyConverterSig], _AnyConverterSig] = (), + channel_types: collections.Sequence[int] | None = None, + choices: ( + collections.Mapping[str, str | int | float] + | collections.Sequence[tuple[str, str | int | float]] + | collections.Sequence[hikari.CommandChoice] + | None + ) = None, + converters: collections.Sequence[_AnyConverterSig] | _AnyConverterSig = (), default: typing.Any = tanjun.NO_DEFAULT, - key: typing.Optional[str] = None, - min_length: typing.Optional[int] = None, - max_length: typing.Optional[int] = None, - min_value: typing.Union[int, float, None] = None, - max_value: typing.Union[int, float, None] = None, + key: str | None = None, + min_length: int | None = None, + max_length: int | None = None, + min_value: int | float | None = None, + max_value: int | float | None = None, only_member: bool = False, pass_as_kwarg: bool = True, _stack_level: int = 0, @@ -1779,7 +1769,7 @@ def _add_option( ) if choices is None: - actual_choices: typing.Optional[list[hikari.CommandChoice]] = None + actual_choices: list[hikari.CommandChoice] | None = None elif isinstance(choices, collections.Mapping): actual_choices = [hikari.CommandChoice(name=name, value=value) for name, value in choices.items()] @@ -1838,12 +1828,12 @@ def _add_option( def add_attachment_option( self, - name: typing.Union[str, collections.Mapping[str, str]], - description: typing.Union[str, collections.Mapping[str, str]], + name: str | collections.Mapping[str, str], + description: str | collections.Mapping[str, str], /, *, default: typing.Any = tanjun.NO_DEFAULT, - key: typing.Optional[str] = None, + key: str | None = None, pass_as_kwarg: bool = True, ) -> Self: r"""Add an attachment option to the slash command. @@ -1911,19 +1901,22 @@ def add_attachment_option( @typing.overload def add_str_option( self, - name: typing.Union[str, collections.Mapping[str, str]], - description: typing.Union[str, collections.Mapping[str, str]], + name: str | collections.Mapping[str, str], + description: str | collections.Mapping[str, str], /, *, - autocomplete: typing.Optional[tanjun.AutocompleteSig[str]] = None, - choices: typing.Union[ - collections.Mapping[str, str], collections.Sequence[str], collections.Sequence[hikari.CommandChoice], None - ] = None, - converters: typing.Union[collections.Sequence[ConverterSig[str]], ConverterSig[str]] = (), + autocomplete: tanjun.AutocompleteSig[str] | None = None, + choices: ( + collections.Mapping[str, str] + | collections.Sequence[str] + | collections.Sequence[hikari.CommandChoice] + | None + ) = None, + converters: collections.Sequence[ConverterSig[str]] | ConverterSig[str] = (), default: typing.Any = tanjun.NO_DEFAULT, - key: typing.Optional[str] = None, - min_length: typing.Optional[int] = None, - max_length: typing.Optional[int] = None, + key: str | None = None, + min_length: int | None = None, + max_length: int | None = None, pass_as_kwarg: bool = True, _stack_level: int = 0, ) -> Self: ... @@ -1932,40 +1925,40 @@ def add_str_option( @typing_extensions.deprecated("Pass a dict for `choices`, not a sequence of tuples") def add_str_option( self, - name: typing.Union[str, collections.Mapping[str, str]], - description: typing.Union[str, collections.Mapping[str, str]], + name: str | collections.Mapping[str, str], + description: str | collections.Mapping[str, str], /, *, - autocomplete: typing.Optional[tanjun.AutocompleteSig[str]] = None, + autocomplete: tanjun.AutocompleteSig[str] | None = None, choices: collections.Sequence[tuple[str, str]], - converters: typing.Union[collections.Sequence[ConverterSig[str]], ConverterSig[str]] = (), + converters: collections.Sequence[ConverterSig[str]] | ConverterSig[str] = (), default: typing.Any = tanjun.NO_DEFAULT, - key: typing.Optional[str] = None, - min_length: typing.Optional[int] = None, - max_length: typing.Optional[int] = None, + key: str | None = None, + min_length: int | None = None, + max_length: int | None = None, pass_as_kwarg: bool = True, _stack_level: int = 0, ) -> Self: ... def add_str_option( self, - name: typing.Union[str, collections.Mapping[str, str]], - description: typing.Union[str, collections.Mapping[str, str]], + name: str | collections.Mapping[str, str], + description: str | collections.Mapping[str, str], /, *, - autocomplete: typing.Optional[tanjun.AutocompleteSig[str]] = None, - choices: typing.Union[ - collections.Mapping[str, str], - collections.Sequence[str], - collections.Sequence[tuple[str, str]], - collections.Sequence[hikari.CommandChoice], - None, - ] = None, - converters: typing.Union[collections.Sequence[ConverterSig[str]], ConverterSig[str]] = (), + autocomplete: tanjun.AutocompleteSig[str] | None = None, + choices: ( + collections.Mapping[str, str] + | collections.Sequence[str] + | collections.Sequence[tuple[str, str]] + | collections.Sequence[hikari.CommandChoice] + | None + ) = None, + converters: collections.Sequence[ConverterSig[str]] | ConverterSig[str] = (), default: typing.Any = tanjun.NO_DEFAULT, - key: typing.Optional[str] = None, - min_length: typing.Optional[int] = None, - max_length: typing.Optional[int] = None, + key: str | None = None, + min_length: int | None = None, + max_length: int | None = None, pass_as_kwarg: bool = True, _stack_level: int = 0, ) -> Self: @@ -2061,7 +2054,7 @@ def add_str_option( * If `max_length` is less than `1` or greater than `6000`. """ # noqa: E501 if choices is None or isinstance(choices, collections.Mapping): - actual_choices: typing.Union[collections.Mapping[str, str], list[hikari.CommandChoice], None] = choices + actual_choices: collections.Mapping[str, str] | list[hikari.CommandChoice] | None = choices else: actual_choices = [] @@ -2109,17 +2102,17 @@ def add_str_option( @typing.overload def add_int_option( self, - name: typing.Union[str, collections.Mapping[str, str]], - description: typing.Union[str, collections.Mapping[str, str]], + name: str | collections.Mapping[str, str], + description: str | collections.Mapping[str, str], /, *, - autocomplete: typing.Optional[tanjun.AutocompleteSig[int]] = None, - choices: typing.Union[collections.Mapping[str, int], collections.Sequence[hikari.CommandChoice], None] = None, - converters: typing.Union[collections.Sequence[ConverterSig[int]], ConverterSig[int]] = (), + autocomplete: tanjun.AutocompleteSig[int] | None = None, + choices: collections.Mapping[str, int] | collections.Sequence[hikari.CommandChoice] | None = None, + converters: collections.Sequence[ConverterSig[int]] | ConverterSig[int] = (), default: typing.Any = tanjun.NO_DEFAULT, - key: typing.Optional[str] = None, - min_value: typing.Optional[int] = None, - max_value: typing.Optional[int] = None, + key: str | None = None, + min_value: int | None = None, + max_value: int | None = None, pass_as_kwarg: bool = True, _stack_level: int = 0, ) -> Self: ... @@ -2128,39 +2121,39 @@ def add_int_option( @typing_extensions.deprecated("Pass a dict for choices, not a sequence of tuples") def add_int_option( self, - name: typing.Union[str, collections.Mapping[str, str]], - description: typing.Union[str, collections.Mapping[str, str]], + name: str | collections.Mapping[str, str], + description: str | collections.Mapping[str, str], /, *, - autocomplete: typing.Optional[tanjun.AutocompleteSig[int]] = None, + autocomplete: tanjun.AutocompleteSig[int] | None = None, choices: collections.Sequence[tuple[str, int]], - converters: typing.Union[collections.Sequence[ConverterSig[int]], ConverterSig[int]] = (), + converters: collections.Sequence[ConverterSig[int]] | ConverterSig[int] = (), default: typing.Any = tanjun.NO_DEFAULT, - key: typing.Optional[str] = None, - min_value: typing.Optional[int] = None, - max_value: typing.Optional[int] = None, + key: str | None = None, + min_value: int | None = None, + max_value: int | None = None, pass_as_kwarg: bool = True, _stack_level: int = 0, ) -> Self: ... def add_int_option( self, - name: typing.Union[str, collections.Mapping[str, str]], - description: typing.Union[str, collections.Mapping[str, str]], + name: str | collections.Mapping[str, str], + description: str | collections.Mapping[str, str], /, *, - autocomplete: typing.Optional[tanjun.AutocompleteSig[int]] = None, - choices: typing.Union[ - collections.Mapping[str, int], - collections.Sequence[tuple[str, int]], - collections.Sequence[hikari.CommandChoice], - None, - ] = None, - converters: typing.Union[collections.Sequence[ConverterSig[int]], ConverterSig[int]] = (), + autocomplete: tanjun.AutocompleteSig[int] | None = None, + choices: ( + collections.Mapping[str, int] + | collections.Sequence[tuple[str, int]] + | collections.Sequence[hikari.CommandChoice] + | None + ) = None, + converters: collections.Sequence[ConverterSig[int]] | ConverterSig[int] = (), default: typing.Any = tanjun.NO_DEFAULT, - key: typing.Optional[str] = None, - min_value: typing.Optional[int] = None, - max_value: typing.Optional[int] = None, + key: str | None = None, + min_value: int | None = None, + max_value: int | None = None, pass_as_kwarg: bool = True, _stack_level: int = 0, ) -> Self: @@ -2264,18 +2257,18 @@ def add_int_option( @typing.overload def add_float_option( self, - name: typing.Union[str, collections.Mapping[str, str]], - description: typing.Union[str, collections.Mapping[str, str]], + name: str | collections.Mapping[str, str], + description: str | collections.Mapping[str, str], /, *, always_float: bool = True, - autocomplete: typing.Optional[tanjun.AutocompleteSig[float]] = None, - choices: typing.Union[collections.Mapping[str, float], collections.Sequence[hikari.CommandChoice], None] = None, - converters: typing.Union[collections.Sequence[ConverterSig[float]], ConverterSig[float]] = (), + autocomplete: tanjun.AutocompleteSig[float] | None = None, + choices: collections.Mapping[str, float] | collections.Sequence[hikari.CommandChoice] | None = None, + converters: collections.Sequence[ConverterSig[float]] | ConverterSig[float] = (), default: typing.Any = tanjun.NO_DEFAULT, - key: typing.Optional[str] = None, - min_value: typing.Optional[float] = None, - max_value: typing.Optional[float] = None, + key: str | None = None, + min_value: float | None = None, + max_value: float | None = None, pass_as_kwarg: bool = True, _stack_level: int = 0, ) -> Self: ... @@ -2284,41 +2277,41 @@ def add_float_option( @typing_extensions.deprecated("Pass a dict for choices, not a sequence of tuples") def add_float_option( self, - name: typing.Union[str, collections.Mapping[str, str]], - description: typing.Union[str, collections.Mapping[str, str]], + name: str | collections.Mapping[str, str], + description: str | collections.Mapping[str, str], /, *, always_float: bool = True, - autocomplete: typing.Optional[tanjun.AutocompleteSig[float]] = None, + autocomplete: tanjun.AutocompleteSig[float] | None = None, choices: collections.Sequence[tuple[str, float]], - converters: typing.Union[collections.Sequence[ConverterSig[float]], ConverterSig[float]] = (), + converters: collections.Sequence[ConverterSig[float]] | ConverterSig[float] = (), default: typing.Any = tanjun.NO_DEFAULT, - key: typing.Optional[str] = None, - min_value: typing.Optional[float] = None, - max_value: typing.Optional[float] = None, + key: str | None = None, + min_value: float | None = None, + max_value: float | None = None, pass_as_kwarg: bool = True, _stack_level: int = 0, ) -> Self: ... def add_float_option( self, - name: typing.Union[str, collections.Mapping[str, str]], - description: typing.Union[str, collections.Mapping[str, str]], + name: str | collections.Mapping[str, str], + description: str | collections.Mapping[str, str], /, *, always_float: bool = True, - autocomplete: typing.Optional[tanjun.AutocompleteSig[float]] = None, - choices: typing.Union[ - collections.Mapping[str, float], - collections.Sequence[tuple[str, float]], - collections.Sequence[hikari.CommandChoice], - None, - ] = None, - converters: typing.Union[collections.Sequence[ConverterSig[float]], ConverterSig[float]] = (), + autocomplete: tanjun.AutocompleteSig[float] | None = None, + choices: ( + collections.Mapping[str, float] + | collections.Sequence[tuple[str, float]] + | collections.Sequence[hikari.CommandChoice] + | None + ) = None, + converters: collections.Sequence[ConverterSig[float]] | ConverterSig[float] = (), default: typing.Any = tanjun.NO_DEFAULT, - key: typing.Optional[str] = None, - min_value: typing.Optional[float] = None, - max_value: typing.Optional[float] = None, + key: str | None = None, + min_value: float | None = None, + max_value: float | None = None, pass_as_kwarg: bool = True, _stack_level: int = 0, ) -> Self: @@ -2428,12 +2421,12 @@ def add_float_option( def add_bool_option( self, - name: typing.Union[str, collections.Mapping[str, str]], - description: typing.Union[str, collections.Mapping[str, str]], + name: str | collections.Mapping[str, str], + description: str | collections.Mapping[str, str], /, *, default: typing.Any = tanjun.NO_DEFAULT, - key: typing.Optional[str] = None, + key: str | None = None, pass_as_kwarg: bool = True, ) -> Self: r"""Add a boolean option to a slash command. @@ -2495,12 +2488,12 @@ def add_bool_option( def add_user_option( self, - name: typing.Union[str, collections.Mapping[str, str]], - description: typing.Union[str, collections.Mapping[str, str]], + name: str | collections.Mapping[str, str], + description: str | collections.Mapping[str, str], /, *, default: typing.Any = tanjun.NO_DEFAULT, - key: typing.Optional[str] = None, + key: str | None = None, pass_as_kwarg: bool = True, ) -> Self: r"""Add a user option to a slash command. @@ -2569,12 +2562,12 @@ def add_user_option( def add_member_option( self, - name: typing.Union[str, collections.Mapping[str, str]], - description: typing.Union[str, collections.Mapping[str, str]], + name: str | collections.Mapping[str, str], + description: str | collections.Mapping[str, str], /, *, default: typing.Any = tanjun.NO_DEFAULT, - key: typing.Optional[str] = None, + key: str | None = None, ) -> Self: r"""Add a member option to a slash command. @@ -2639,13 +2632,13 @@ def add_member_option( def add_channel_option( self, - name: typing.Union[str, collections.Mapping[str, str]], - description: typing.Union[str, collections.Mapping[str, str]], + name: str | collections.Mapping[str, str], + description: str | collections.Mapping[str, str], /, *, default: typing.Any = tanjun.NO_DEFAULT, - key: typing.Optional[str] = None, - types: typing.Optional[collections.Collection[typing.Union[type[hikari.PartialChannel], int]]] = None, + key: str | None = None, + types: collections.Collection[type[hikari.PartialChannel] | int] | None = None, pass_as_kwarg: bool = True, ) -> Self: r"""Add a channel option to a slash command. @@ -2717,12 +2710,12 @@ def add_channel_option( def add_role_option( self, - name: typing.Union[str, collections.Mapping[str, str]], - description: typing.Union[str, collections.Mapping[str, str]], + name: str | collections.Mapping[str, str], + description: str | collections.Mapping[str, str], /, *, default: typing.Any = tanjun.NO_DEFAULT, - key: typing.Optional[str] = None, + key: str | None = None, pass_as_kwarg: bool = True, ) -> Self: r"""Add a role option to a slash command. @@ -2784,12 +2777,12 @@ def add_role_option( def add_mentionable_option( self, - name: typing.Union[str, collections.Mapping[str, str]], - description: typing.Union[str, collections.Mapping[str, str]], + name: str | collections.Mapping[str, str], + description: str | collections.Mapping[str, str], /, *, default: typing.Any = tanjun.NO_DEFAULT, - key: typing.Optional[str] = None, + key: str | None = None, pass_as_kwarg: bool = True, ) -> Self: r"""Add a mentionable option to a slash command. @@ -2853,7 +2846,7 @@ def add_mentionable_option( pass_as_kwarg=pass_as_kwarg, ) - def set_float_autocomplete(self, name: str, callback: typing.Optional[tanjun.AutocompleteSig[float]], /) -> Self: + def set_float_autocomplete(self, name: str, callback: tanjun.AutocompleteSig[float] | None, /) -> Self: """Set the autocomplete callback for a float option. Parameters @@ -3097,7 +3090,7 @@ def decorator(callback: _StrAutocompleteSigT, /) -> _StrAutocompleteSigT: async def _process_args(self, ctx: tanjun.SlashContext, /) -> collections.Mapping[str, typing.Any]: keyword_args: dict[ - str, typing.Union[int, float, str, hikari.Attachment, hikari.User, hikari.Role, hikari.InteractionChannel] + str, int | float | str | hikari.Attachment | hikari.User | hikari.Role | hikari.InteractionChannel ] = {} for tracked_option in self._tracked_options.values(): if not (option := ctx.options.get(tracked_option.name)): @@ -3111,7 +3104,7 @@ async def _process_args(self, ctx: tanjun.SlashContext, /) -> collections.Mappin keyword_args[tracked_option.key] = tracked_option.default elif option.type is hikari.OptionType.USER: - member: typing.Optional[hikari.InteractionMember] = None + member: hikari.InteractionMember | None = None if tracked_option.is_only_member and not (member := option.resolve_to_member(default=None)): raise errors.ConversionError( f"Couldn't find member for provided user: {option.value}", tracked_option.name @@ -3150,8 +3143,8 @@ async def execute( ctx: tanjun.SlashContext, /, *, - option: typing.Optional[hikari.CommandInteractionOption] = None, - hooks: typing.Optional[collections.MutableSet[tanjun.SlashHooks]] = None, + option: hikari.CommandInteractionOption | None = None, + hooks: collections.MutableSet[tanjun.SlashHooks] | None = None, ) -> None: # <>. if self._always_defer and not ctx.has_been_deferred and not ctx.has_responded: @@ -3188,11 +3181,7 @@ async def execute( await own_hooks.trigger_post_execution(ctx, hooks=hooks) async def execute_autocomplete( - self, - ctx: tanjun.AutocompleteContext, - /, - *, - option: typing.Optional[hikari.AutocompleteInteractionOption] = None, + self, ctx: tanjun.AutocompleteContext, /, *, option: hikari.AutocompleteInteractionOption | None = None ) -> None: # <>. if ctx.focused.type is hikari.OptionType.STRING: @@ -3212,7 +3201,7 @@ async def execute_autocomplete( await ctx.call_with_async_di(callback, ctx, ctx.focused.value) - def copy(self, *, parent: typing.Optional[tanjun.SlashCommandGroup] = None) -> Self: + def copy(self, *, parent: tanjun.SlashCommandGroup | None = None) -> Self: # <>. inst = super().copy(parent=parent) inst._callback = copy.copy(self._callback) diff --git a/tanjun/components.py b/tanjun/components.py index e79545778..231439cd5 100644 --- a/tanjun/components.py +++ b/tanjun/components.py @@ -49,7 +49,7 @@ from . import abc as tanjun if typing.TYPE_CHECKING: - from typing_extensions import Self + from typing import Self from . import schedules as schedules_ @@ -65,11 +65,12 @@ _ScheduleT = typing.TypeVar("_ScheduleT", bound=schedules_.AbstractSchedule) _CommandT = typing.TypeVar("_CommandT", bound="tanjun.ExecutableCommand[typing.Any]") + # Pyright bug doesn't accept Var = Class | Class as a type _WithCommandReturnSig = typing.Union[_CommandT, "collections.Callable[[_CommandT], _CommandT]"] _LOGGER = logging.getLogger("hikari.tanjun.components") -OnCallbackSig = collections.Callable[..., typing.Optional[collections.Coroutine[typing.Any, typing.Any, None]]] +OnCallbackSig = collections.Callable[..., collections.Coroutine[typing.Any, typing.Any, None] | None] """Type hint of a on_open or on_close component callback. This represents the signatures `def (...) -> None` and `async def (...) -> None` @@ -95,7 +96,7 @@ def load_into_component(self, component: tanjun.Component, /) -> None: def _with_command( add_command: collections.Callable[[_CommandT], Component], - maybe_command: typing.Optional[_CommandT], + maybe_command: _CommandT | None, /, *, copy: bool = False, @@ -178,7 +179,7 @@ class Component(tanjun.Component): "_tasks", ) - def __init__(self, *, name: typing.Optional[str] = None, strict: bool = False) -> None: + def __init__(self, *, name: str | None = None, strict: bool = False) -> None: """Initialise a new component. Parameters @@ -195,33 +196,33 @@ def __init__(self, *, name: typing.Optional[str] = None, strict: bool = False) - spaces and will have to be unique to one command within the component. """ self._checks: list[tanjun.AnyCheckSig] = [] - self._client: typing.Optional[tanjun.Client] = None + self._client: tanjun.Client | None = None self._client_callbacks: dict[str, list[tanjun.MetaEventSig]] = {} - self._default_app_cmd_permissions: typing.Optional[hikari.Permissions] = None - self._defaults_to_ephemeral: typing.Optional[bool] = None - self._dms_enabled_for_app_cmds: typing.Optional[bool] = None - self._hooks: typing.Optional[tanjun.AnyHooks] = None - self._is_case_sensitive: typing.Optional[bool] = None + self._default_app_cmd_permissions: hikari.Permissions | None = None + self._defaults_to_ephemeral: bool | None = None + self._dms_enabled_for_app_cmds: bool | None = None + self._hooks: tanjun.AnyHooks | None = None + self._is_case_sensitive: bool | None = None self._listeners: dict[type[hikari.Event], list[tanjun.ListenerCallbackSig[typing.Any]]] = {} - self._loop: typing.Optional[asyncio.AbstractEventLoop] = None + self._loop: asyncio.AbstractEventLoop | None = None self._menu_commands: dict[tuple[hikari.CommandType, str], tanjun.MenuCommand[typing.Any, typing.Any]] = {} - self._menu_hooks: typing.Optional[tanjun.MenuHooks] = None + self._menu_hooks: tanjun.MenuHooks | None = None self._message_commands = _internal.MessageCommandIndex(strict) - self._message_hooks: typing.Optional[tanjun.MessageHooks] = None + self._message_hooks: tanjun.MessageHooks | None = None self._metadata: dict[typing.Any, typing.Any] = {} self._name = name or str(uuid.uuid4()) self._on_close: list[OnCallbackSig] = [] self._on_open: list[OnCallbackSig] = [] self._schedules: list[schedules_.AbstractSchedule] = [] self._slash_commands: dict[str, tanjun.BaseSlashCommand] = {} - self._slash_hooks: typing.Optional[tanjun.SlashHooks] = None + self._slash_hooks: tanjun.SlashHooks | None = None self._tasks: list[asyncio.Task[typing.Any]] = [] def __repr__(self) -> str: return f"{type(self).__name__}({self.checks=}, {self.hooks=}, {self.slash_hooks=}, {self.message_hooks=})" @property - def is_case_sensitive(self) -> typing.Optional[bool]: + def is_case_sensitive(self) -> bool | None: # <>. return self._is_case_sensitive @@ -231,46 +232,46 @@ def checks(self) -> collections.Collection[tanjun.AnyCheckSig]: return self._checks.copy() @property - def client(self) -> typing.Optional[tanjun.Client]: + def client(self) -> tanjun.Client | None: # <>. return self._client @property - def default_app_cmd_permissions(self) -> typing.Optional[hikari.Permissions]: + def default_app_cmd_permissions(self) -> hikari.Permissions | None: return self._default_app_cmd_permissions @property - def defaults_to_ephemeral(self) -> typing.Optional[bool]: + def defaults_to_ephemeral(self) -> bool | None: # <>. return self._defaults_to_ephemeral @property - def dms_enabled_for_app_cmds(self) -> typing.Optional[bool]: + def dms_enabled_for_app_cmds(self) -> bool | None: # <>. return self._dms_enabled_for_app_cmds @property - def hooks(self) -> typing.Optional[tanjun.AnyHooks]: + def hooks(self) -> tanjun.AnyHooks | None: """The general command hooks set for this component, if any.""" return self._hooks @property - def menu_hooks(self) -> typing.Optional[tanjun.MenuHooks]: + def menu_hooks(self) -> tanjun.MenuHooks | None: """The menu command hooks set for this component, if any.""" return self._menu_hooks @property - def message_hooks(self) -> typing.Optional[tanjun.MessageHooks]: + def message_hooks(self) -> tanjun.MessageHooks | None: """The message command hooks set for this component, if any.""" return self._message_hooks @property - def slash_hooks(self) -> typing.Optional[tanjun.SlashHooks]: + def slash_hooks(self) -> tanjun.SlashHooks | None: """The slash command hooks set for this component, if any.""" return self._slash_hooks @property - def loop(self) -> typing.Optional[asyncio.AbstractEventLoop]: + def loop(self) -> asyncio.AbstractEventLoop | None: # <>. return self._loop @@ -334,13 +335,13 @@ def copy(self) -> Self: return inst @typing.overload - def load_from_scope(self, *, scope: typing.Optional[collections.Mapping[str, typing.Any]] = None) -> Self: ... + def load_from_scope(self, *, scope: collections.Mapping[str, typing.Any] | None = None) -> Self: ... @typing.overload def load_from_scope(self, *, include_globals: bool = False) -> Self: ... def load_from_scope( - self, *, include_globals: bool = False, scope: typing.Optional[collections.Mapping[str, typing.Any]] = None + self, *, include_globals: bool = False, scope: collections.Mapping[str, typing.Any] | None = None ) -> Self: """Load entries such as top-level commands into the component from the calling scope. @@ -412,7 +413,7 @@ def load_from_scope( return self - def set_case_sensitive(self, state: typing.Optional[bool], /) -> Self: + def set_case_sensitive(self, state: bool | None, /) -> Self: """Set whether this component defaults to being case sensitive for component. Parameters @@ -427,7 +428,7 @@ def set_case_sensitive(self, state: typing.Optional[bool], /) -> Self: self._is_case_sensitive = state return self - def set_default_app_command_permissions(self, permissions: typing.Union[int, hikari.Permissions, None], /) -> Self: + def set_default_app_command_permissions(self, permissions: int | hikari.Permissions | None, /) -> Self: """Set the default member permissions needed for this component's commands. !!! warning @@ -454,7 +455,7 @@ def set_default_app_command_permissions(self, permissions: typing.Union[int, hik self._default_app_cmd_permissions = hikari.Permissions(permissions) if permissions is not None else None return self - def set_dms_enabled_for_app_cmds(self, state: typing.Optional[bool], /) -> Self: + def set_dms_enabled_for_app_cmds(self, state: bool | None, /) -> Self: """Set whether this component's commands should be enabled in DMs. Parameters @@ -475,7 +476,7 @@ def set_dms_enabled_for_app_cmds(self, state: typing.Optional[bool], /) -> Self: self._dms_enabled_for_app_cmds = state return self - def set_ephemeral_default(self, state: typing.Optional[bool], /) -> Self: + def set_ephemeral_default(self, state: bool | None, /) -> Self: """Set whether slash contexts executed in this component should default to ephemeral responses. Parameters @@ -501,7 +502,7 @@ def set_metadata(self, key: typing.Any, value: typing.Any, /) -> Self: self._metadata[key] = value return self - def set_hooks(self, hooks: typing.Optional[tanjun.AnyHooks], /) -> Self: + def set_hooks(self, hooks: tanjun.AnyHooks | None, /) -> Self: """Set hooks to be called during the execution of all of this component's commands. Parameters @@ -517,7 +518,7 @@ def set_hooks(self, hooks: typing.Optional[tanjun.AnyHooks], /) -> Self: self._hooks = hooks return self - def set_menu_hooks(self, hooks: typing.Optional[tanjun.MenuHooks], /) -> Self: + def set_menu_hooks(self, hooks: tanjun.MenuHooks | None, /) -> Self: """Set hooks to be called during the execution of this component's menu commands. Parameters @@ -533,7 +534,7 @@ def set_menu_hooks(self, hooks: typing.Optional[tanjun.MenuHooks], /) -> Self: self._menu_hooks = hooks return self - def set_message_hooks(self, hooks: typing.Optional[tanjun.MessageHooks], /) -> Self: + def set_message_hooks(self, hooks: tanjun.MessageHooks | None, /) -> Self: """Set hooks to be called during the execution of this component's message commands. Parameters @@ -549,7 +550,7 @@ def set_message_hooks(self, hooks: typing.Optional[tanjun.MessageHooks], /) -> S self._message_hooks = hooks return self - def set_slash_hooks(self, hooks: typing.Optional[tanjun.SlashHooks], /) -> Self: + def set_slash_hooks(self, hooks: tanjun.SlashHooks | None, /) -> Self: """Set hooks to be called during the execution of this component's slash commands. Parameters @@ -621,9 +622,7 @@ def with_check(self, check: _CheckSigT, /) -> _CheckSigT: self.add_check(check) return check - def add_client_callback( - self, name: typing.Union[str, tanjun.ClientCallbackNames], /, *callbacks: tanjun.MetaEventSig - ) -> Self: + def add_client_callback(self, name: str | tanjun.ClientCallbackNames, /, *callbacks: tanjun.MetaEventSig) -> Self: """Add a client callback. Parameters @@ -662,7 +661,7 @@ def add_client_callback( return self def get_client_callbacks( - self, name: typing.Union[str, tanjun.ClientCallbackNames], / + self, name: str | tanjun.ClientCallbackNames, / ) -> collections.Collection[tanjun.MetaEventSig]: """Get a collection of the callbacks registered for a specific name. @@ -714,7 +713,7 @@ def remove_client_callback(self, name: str, callback: tanjun.MetaEventSig, /) -> self._client.remove_client_callback(name, callback) def with_client_callback( - self, name: typing.Union[str, tanjun.ClientCallbackNames], / + self, name: str | tanjun.ClientCallbackNames, / ) -> collections.Callable[[_MetaEventSigT], _MetaEventSigT]: """Add a client callback through a decorator call. @@ -819,7 +818,7 @@ def with_command( ) -> collections.Callable[[_CommandT], _CommandT]: ... def with_command( - self, command: typing.Optional[_CommandT] = None, /, *, copy: bool = False, follow_wrapped: bool = False + self, command: _CommandT | None = None, /, *, copy: bool = False, follow_wrapped: bool = False ) -> _WithCommandReturnSig[_CommandT]: """Add a command to this component through a decorator call. @@ -891,7 +890,7 @@ def with_menu_command(self, command: _MenuCommandT, /) -> _MenuCommandT: ... def with_menu_command(self, /, *, copy: bool = False) -> collections.Callable[[_MenuCommandT], _MenuCommandT]: ... def with_menu_command( - self, command: typing.Optional[_MenuCommandT] = None, /, *, copy: bool = False + self, command: _MenuCommandT | None = None, /, *, copy: bool = False ) -> _WithCommandReturnSig[_MenuCommandT]: # <>. return _with_command(self.add_menu_command, command, copy=copy) @@ -927,7 +926,7 @@ def with_slash_command( ) -> collections.Callable[[_BaseSlashCommandT], _BaseSlashCommandT]: ... def with_slash_command( - self, command: typing.Optional[_BaseSlashCommandT] = None, /, *, copy: bool = False + self, command: _BaseSlashCommandT | None = None, /, *, copy: bool = False ) -> _WithCommandReturnSig[_BaseSlashCommandT]: # <>. return _with_command(self.add_slash_command, command, copy=copy) @@ -973,7 +972,7 @@ def with_message_command( ) -> collections.Callable[[_MessageCommandT], _MessageCommandT]: ... def with_message_command( - self, command: typing.Optional[_MessageCommandT] = None, /, *, copy: bool = False + self, command: _MessageCommandT | None = None, /, *, copy: bool = False ) -> _WithCommandReturnSig[_MessageCommandT]: # <>. return _with_command(self.add_message_command, command, copy=copy) @@ -1197,7 +1196,7 @@ def check_slash_name(self, name: str, /) -> collections.Iterator[tanjun.BaseSlas def execute_autocomplete( self, ctx: tanjun.AutocompleteContext, / - ) -> typing.Optional[collections.Coroutine[typing.Any, typing.Any, None]]: + ) -> collections.Coroutine[typing.Any, typing.Any, None] | None: # <>. if command := self._slash_commands.get(ctx.interaction.command_name): return command.execute_autocomplete(ctx) @@ -1207,12 +1206,12 @@ def execute_autocomplete( async def _execute_app( self, ctx: _AppCommandContextT, - command: typing.Optional[tanjun.AppCommand[_AppCommandContextT]], + command: tanjun.AppCommand[_AppCommandContextT] | None, /, *, - hooks: typing.Optional[collections.MutableSet[tanjun.Hooks[_AppCommandContextT]]] = None, - other_hooks: typing.Optional[tanjun.Hooks[_AppCommandContextT]] = None, - ) -> typing.Optional[collections.Coroutine[typing.Any, typing.Any, None]]: + hooks: collections.MutableSet[tanjun.Hooks[_AppCommandContextT]] | None = None, + other_hooks: tanjun.Hooks[_AppCommandContextT] | None = None, + ) -> collections.Coroutine[typing.Any, typing.Any, None] | None: if not command or not await self._check_context(ctx) or not await command.check_context(ctx): return None @@ -1234,10 +1233,8 @@ async def _execute_app( # a match is found the public function is kept sync to avoid yielding # to the event loop until after this is set. def execute_menu( - self, ctx: tanjun.MenuContext, /, *, hooks: typing.Optional[collections.MutableSet[tanjun.MenuHooks]] = None - ) -> collections.Coroutine[ - typing.Any, typing.Any, typing.Optional[collections.Coroutine[typing.Any, typing.Any, None]] - ]: + self, ctx: tanjun.MenuContext, /, *, hooks: collections.MutableSet[tanjun.MenuHooks] | None = None + ) -> collections.Coroutine[typing.Any, typing.Any, collections.Coroutine[typing.Any, typing.Any, None] | None]: # <>. command = self._menu_commands.get((ctx.type, ctx.interaction.command_name)) if command: @@ -1253,10 +1250,8 @@ def execute_menu( # a match is found the public function is kept sync to avoid yielding # to the event loop until after this is set. def execute_slash( - self, ctx: tanjun.SlashContext, /, *, hooks: typing.Optional[collections.MutableSet[tanjun.SlashHooks]] = None - ) -> collections.Coroutine[ - typing.Any, typing.Any, typing.Optional[collections.Coroutine[typing.Any, typing.Any, None]] - ]: + self, ctx: tanjun.SlashContext, /, *, hooks: collections.MutableSet[tanjun.SlashHooks] | None = None + ) -> collections.Coroutine[typing.Any, typing.Any, collections.Coroutine[typing.Any, typing.Any, None] | None]: # <>. command = self._slash_commands.get(ctx.interaction.command_name) if command: @@ -1269,11 +1264,7 @@ def execute_slash( return self._execute_app(ctx, command, hooks=hooks, other_hooks=self._slash_hooks) async def execute_message( - self, - ctx: tanjun.MessageContext, - /, - *, - hooks: typing.Optional[collections.MutableSet[tanjun.MessageHooks]] = None, + self, ctx: tanjun.MessageContext, /, *, hooks: collections.MutableSet[tanjun.MessageHooks] | None = None ) -> bool: # <>. async for name, command in self._check_message_context(ctx): diff --git a/tanjun/context/autocomplete.py b/tanjun/context/autocomplete.py index b5d8b13cc..c3eaee4da 100644 --- a/tanjun/context/autocomplete.py +++ b/tanjun/context/autocomplete.py @@ -61,7 +61,7 @@ def __init__( client: tanjun.Client, interaction: hikari.AutocompleteInteraction, *, - future: typing.Optional[asyncio.Future[hikari.api.InteractionAutocompleteBuilder]] = None, + future: asyncio.Future[hikari.api.InteractionAutocompleteBuilder] | None = None, ) -> None: """Initialise an autocomplete context. @@ -81,7 +81,7 @@ def __init__( self._has_responded = False self._interaction = interaction - focused: typing.Optional[hikari.AutocompleteInteractionOption] = None + focused: hikari.AutocompleteInteractionOption | None = None self._options: dict[str, hikari.AutocompleteInteractionOption] = {} command_name, options = _internal.flatten_options(interaction.command_name, interaction.options) for option in options: @@ -105,7 +105,7 @@ def channel_id(self) -> hikari.Snowflake: return self._interaction.channel_id @property - def cache(self) -> typing.Optional[hikari.api.Cache]: + def cache(self) -> hikari.api.Cache | None: # <>. return self._tanjun_client.cache @@ -125,7 +125,7 @@ def created_at(self) -> datetime.datetime: return self._interaction.created_at @property - def events(self) -> typing.Optional[hikari.api.EventManager]: + def events(self) -> hikari.api.EventManager | None: # <>. return self._tanjun_client.events @@ -135,17 +135,17 @@ def focused(self) -> hikari.AutocompleteInteractionOption: return self._focused @property - def guild_id(self) -> typing.Optional[hikari.Snowflake]: + def guild_id(self) -> hikari.Snowflake | None: # <>. return self._interaction.guild_id @property - def member(self) -> typing.Optional[hikari.Member]: + def member(self) -> hikari.Member | None: # <>. return self._interaction.member @property - def server(self) -> typing.Optional[hikari.api.InteractionServer]: + def server(self) -> hikari.api.InteractionServer | None: # <>. return self._tanjun_client.server @@ -155,7 +155,7 @@ def rest(self) -> hikari.api.RESTClient: return self._tanjun_client.rest @property - def shard(self) -> typing.Optional[hikari.api.GatewayShard]: + def shard(self) -> hikari.api.GatewayShard | None: # <>. if not self._tanjun_client.shards: return None @@ -169,12 +169,12 @@ def shard(self) -> typing.Optional[hikari.api.GatewayShard]: return self._tanjun_client.shards.shards[shard_id] @property - def shards(self) -> typing.Optional[hikari.ShardAware]: + def shards(self) -> hikari.ShardAware | None: # <>. return self._tanjun_client.shards @property - def voice(self) -> typing.Optional[hikari.api.VoiceComponent]: + def voice(self) -> hikari.api.VoiceComponent | None: # <>. return self._tanjun_client.voice @@ -197,21 +197,21 @@ async def fetch_channel(self) -> hikari.TextableChannel: # <>. return await self._interaction.fetch_channel() - async def fetch_guild(self) -> typing.Optional[hikari.Guild]: + async def fetch_guild(self) -> hikari.Guild | None: # <>. return await self._interaction.fetch_guild() - def get_channel(self) -> typing.Optional[hikari.TextableGuildChannel]: + def get_channel(self) -> hikari.TextableGuildChannel | None: # <>. return self._interaction.get_channel() - def get_guild(self) -> typing.Optional[hikari.Guild]: + def get_guild(self) -> hikari.Guild | None: # <>. return self._interaction.get_guild() async def set_choices( self, - choices: typing.Union[collections.Mapping[str, _ValueT], collections.Iterable[tuple[str, _ValueT]]] = (), + choices: collections.Mapping[str, _ValueT] | collections.Iterable[tuple[str, _ValueT]] = (), /, **kwargs: _ValueT, ) -> None: diff --git a/tanjun/context/base.py b/tanjun/context/base.py index a4d96dfa7..0d845f4e2 100644 --- a/tanjun/context/base.py +++ b/tanjun/context/base.py @@ -42,7 +42,7 @@ from .. import abc as tanjun if typing.TYPE_CHECKING: - from typing_extensions import Self + from typing import Self class BaseContext(alluka.BasicContext, tanjun.Context): @@ -53,12 +53,12 @@ class BaseContext(alluka.BasicContext, tanjun.Context): def __init__(self, client: tanjun.Client, /) -> None: super().__init__(client.injector) self._tanjun_client = client - self._component: typing.Optional[tanjun.Component] = None + self._component: tanjun.Component | None = None self._final = False self._set_type_special_case(tanjun.Context, self) @property - def cache(self) -> typing.Optional[hikari.api.Cache]: + def cache(self) -> hikari.api.Cache | None: # <>. return self._tanjun_client.cache @@ -68,17 +68,17 @@ def client(self) -> tanjun.Client: return self._tanjun_client @property - def component(self) -> typing.Optional[tanjun.Component]: + def component(self) -> tanjun.Component | None: # <>. return self._component @property - def events(self) -> typing.Optional[hikari.api.EventManager]: + def events(self) -> hikari.api.EventManager | None: # <>. return self._tanjun_client.events @property - def server(self) -> typing.Optional[hikari.api.InteractionServer]: + def server(self) -> hikari.api.InteractionServer | None: # <>. return self._tanjun_client.server @@ -88,7 +88,7 @@ def rest(self) -> hikari.api.RESTClient: return self._tanjun_client.rest @property - def shard(self) -> typing.Optional[hikari.api.GatewayShard]: + def shard(self) -> hikari.api.GatewayShard | None: # <>. if not self._tanjun_client.shards: return None @@ -102,12 +102,12 @@ def shard(self) -> typing.Optional[hikari.api.GatewayShard]: return self._tanjun_client.shards.shards[shard_id] @property - def shards(self) -> typing.Optional[hikari.ShardAware]: + def shards(self) -> hikari.ShardAware | None: # <>. return self._tanjun_client.shards @property - def voice(self) -> typing.Optional[hikari.api.VoiceComponent]: + def voice(self) -> hikari.api.VoiceComponent | None: # <>. return self._tanjun_client.voice @@ -126,7 +126,7 @@ def finalise(self) -> Self: self._final = True return self - def set_component(self, component: typing.Optional[tanjun.Component], /) -> Self: + def set_component(self, component: tanjun.Component | None, /) -> Self: # <>. self._assert_not_final() if component: @@ -138,7 +138,7 @@ def set_component(self, component: typing.Optional[tanjun.Component], /) -> Self self._component = component return self - def get_channel(self) -> typing.Optional[hikari.TextableGuildChannel]: + def get_channel(self) -> hikari.TextableGuildChannel | None: # <>. if self._tanjun_client.cache: channel = self._tanjun_client.cache.get_guild_channel(self.channel_id) @@ -147,7 +147,7 @@ def get_channel(self) -> typing.Optional[hikari.TextableGuildChannel]: return None # MyPy compat - def get_guild(self) -> typing.Optional[hikari.Guild]: + def get_guild(self) -> hikari.Guild | None: # <>. if self.guild_id is not None and self._tanjun_client.cache: return self._tanjun_client.cache.get_guild(self.guild_id) @@ -160,7 +160,7 @@ async def fetch_channel(self) -> hikari.TextableChannel: assert isinstance(channel, hikari.TextableChannel) return channel - async def fetch_guild(self) -> typing.Optional[hikari.Guild]: # TODO: or raise? + async def fetch_guild(self) -> hikari.Guild | None: # TODO: or raise? # <>. if self.guild_id is not None: return await self._tanjun_client.rest.fetch_guild(self.guild_id) diff --git a/tanjun/context/menu.py b/tanjun/context/menu.py index 6e94cb650..d8051f350 100644 --- a/tanjun/context/menu.py +++ b/tanjun/context/menu.py @@ -44,13 +44,14 @@ if typing.TYPE_CHECKING: import asyncio from collections import abc as collections - - from typing_extensions import Self + from typing import Self _T = typing.TypeVar("_T") - _ResponseTypeT = typing.Union[ - hikari.api.InteractionMessageBuilder, hikari.api.InteractionDeferredBuilder, hikari.api.InteractionModalBuilder - ] + _ResponseTypeT = ( + hikari.api.InteractionMessageBuilder + | hikari.api.InteractionDeferredBuilder + | hikari.api.InteractionModalBuilder + ) _VALID_TYPES: frozenset[typing.Literal[hikari.CommandType.USER, hikari.CommandType.MESSAGE]] = frozenset( @@ -70,8 +71,8 @@ def __init__( register_task: collections.Callable[[asyncio.Task[typing.Any]], None], *, default_to_ephemeral: bool = False, - future: typing.Optional[asyncio.Future[_ResponseTypeT]] = None, - on_not_found: typing.Optional[collections.Callable[[tanjun.MenuContext], collections.Awaitable[None]]] = None, + future: asyncio.Future[_ResponseTypeT] | None = None, + on_not_found: collections.Callable[[tanjun.MenuContext], collections.Awaitable[None]] | None = None, ) -> None: """Initialise a menu command context. @@ -92,13 +93,13 @@ def __init__( Callback used to indicate no matching command was found. """ super().__init__(client, interaction, register_task, default_to_ephemeral=default_to_ephemeral, future=future) - self._command: typing.Optional[tanjun.MenuCommand[typing.Any, typing.Any]] = None + self._command: tanjun.MenuCommand[typing.Any, typing.Any] | None = None self._marked_not_found = False self._on_not_found = on_not_found self._set_type_special_case(tanjun.MenuContext, self)._set_type_special_case(MenuContext, self) @property - def command(self) -> typing.Optional[tanjun.MenuCommand[typing.Any, typing.Any]]: + def command(self) -> tanjun.MenuCommand[typing.Any, typing.Any] | None: # <>. return self._command @@ -114,7 +115,7 @@ def target_id(self) -> hikari.Snowflake: return next(iter(mapping.keys())) @property - def target(self) -> typing.Union[hikari.InteractionMember, hikari.User, hikari.Message]: + def target(self) -> hikari.InteractionMember | hikari.User | hikari.Message: # <>. assert self._interaction.resolved mapping = ( @@ -147,7 +148,7 @@ async def mark_not_found(self) -> None: self._marked_not_found = True await self._on_not_found(self) - def set_command(self, command: typing.Optional[tanjun.MenuCommand[typing.Any, typing.Any]], /) -> Self: + def set_command(self, command: tanjun.MenuCommand[typing.Any, typing.Any] | None, /) -> Self: # <>. if command: self._set_type_special_case(tanjun.MenuCommand, command) @@ -162,11 +163,11 @@ def set_command(self, command: typing.Optional[tanjun.MenuCommand[typing.Any, ty def resolve_to_member(self) -> hikari.InteractionMember: ... @typing.overload - def resolve_to_member(self, *, default: _T) -> typing.Union[hikari.InteractionMember, _T]: ... + def resolve_to_member(self, *, default: _T) -> hikari.InteractionMember | _T: ... def resolve_to_member( - self, *, default: typing.Union[_T, _internal.Default] = _internal.DEFAULT - ) -> typing.Union[hikari.InteractionMember, _T]: + self, *, default: _T | _internal.Default = _internal.DEFAULT + ) -> hikari.InteractionMember | _T: # <>. assert self._interaction.resolved if self._interaction.resolved.members: @@ -188,7 +189,7 @@ def resolve_to_message(self) -> hikari.Message: raise TypeError("Cannot resolve user menu context to a message") - def resolve_to_user(self) -> typing.Union[hikari.User, hikari.Member]: + def resolve_to_user(self) -> hikari.User | hikari.Member: # <>. assert self._interaction.resolved return self.resolve_to_member(default=None) or next(iter(self._interaction.resolved.users.values())) diff --git a/tanjun/context/message.py b/tanjun/context/message.py index ccd9e5918..751438919 100644 --- a/tanjun/context/message.py +++ b/tanjun/context/message.py @@ -45,14 +45,13 @@ if typing.TYPE_CHECKING: from collections import abc as collections - - from typing_extensions import Self + from typing import Self _LOGGER = logging.getLogger("hikari.tanjun.context") -def _delete_after_to_float(delete_after: typing.Union[datetime.timedelta, float, int], /) -> float: +def _delete_after_to_float(delete_after: datetime.timedelta | float | int, /) -> float: return delete_after.total_seconds() if isinstance(delete_after, datetime.timedelta) else float(delete_after) @@ -102,10 +101,10 @@ def __init__( raise ValueError("Cannot spawn context with a content-less message.") super().__init__(client) - self._command: typing.Optional[tanjun.MessageCommand[typing.Any]] = None + self._command: tanjun.MessageCommand[typing.Any] | None = None self._content = content - self._initial_response_id: typing.Optional[hikari.Snowflake] = None - self._last_response_id: typing.Optional[hikari.Snowflake] = None + self._initial_response_id: hikari.Snowflake | None = None + self._last_response_id: hikari.Snowflake | None = None self._register_task = register_task self._response_lock = asyncio.Lock() self._message = message @@ -127,7 +126,7 @@ def channel_id(self) -> hikari.Snowflake: return self._message.channel_id @property - def command(self) -> typing.Optional[tanjun.MessageCommand[typing.Any]]: + def command(self) -> tanjun.MessageCommand[typing.Any] | None: # <>. return self._command @@ -142,7 +141,7 @@ def created_at(self) -> datetime.datetime: return self._message.created_at @property - def guild_id(self) -> typing.Optional[hikari.Snowflake]: + def guild_id(self) -> hikari.Snowflake | None: # <>. return self._message.guild_id @@ -157,7 +156,7 @@ def is_human(self) -> bool: return not self._message.author.is_bot and self._message.webhook_id is None @property - def member(self) -> typing.Optional[hikari.Member]: + def member(self) -> hikari.Member | None: # <>. return self._message.member @@ -176,7 +175,7 @@ def triggering_prefix(self) -> str: # <>. return self._triggering_prefix - def set_command(self, command: typing.Optional[tanjun.MessageCommand[typing.Any]], /) -> Self: + def set_command(self, command: tanjun.MessageCommand[typing.Any] | None, /) -> Self: # <>. self._assert_not_final() if command: @@ -238,7 +237,7 @@ async def edit_initial_response( self, content: hikari.UndefinedOr[typing.Any] = hikari.UNDEFINED, *, - delete_after: typing.Union[datetime.timedelta, float, int, None] = None, + delete_after: datetime.timedelta | float | int | None = None, attachment: hikari.UndefinedNoneOr[hikari.Resourceish] = hikari.UNDEFINED, attachments: hikari.UndefinedNoneOr[collections.Sequence[hikari.Resourceish]] = hikari.UNDEFINED, component: hikari.UndefinedNoneOr[hikari.api.ComponentBuilder] = hikari.UNDEFINED, @@ -246,12 +245,8 @@ async def edit_initial_response( embed: hikari.UndefinedNoneOr[hikari.Embed] = hikari.UNDEFINED, embeds: hikari.UndefinedNoneOr[collections.Sequence[hikari.Embed]] = hikari.UNDEFINED, mentions_everyone: hikari.UndefinedOr[bool] = hikari.UNDEFINED, - user_mentions: typing.Union[ - hikari.SnowflakeishSequence[hikari.PartialUser], bool, hikari.UndefinedType - ] = hikari.UNDEFINED, - role_mentions: typing.Union[ - hikari.SnowflakeishSequence[hikari.PartialRole], bool, hikari.UndefinedType - ] = hikari.UNDEFINED, + user_mentions: hikari.SnowflakeishSequence[hikari.PartialUser] | bool | hikari.UndefinedType = hikari.UNDEFINED, + role_mentions: hikari.SnowflakeishSequence[hikari.PartialRole] | bool | hikari.UndefinedType = hikari.UNDEFINED, ) -> hikari.Message: # <>. delete_after = _delete_after_to_float(delete_after) if delete_after is not None else None @@ -281,7 +276,7 @@ async def edit_last_response( self, content: hikari.UndefinedOr[typing.Any] = hikari.UNDEFINED, *, - delete_after: typing.Union[datetime.timedelta, float, int, None] = None, + delete_after: datetime.timedelta | float | int | None = None, attachment: hikari.UndefinedNoneOr[hikari.Resourceish] = hikari.UNDEFINED, attachments: hikari.UndefinedNoneOr[collections.Sequence[hikari.Resourceish]] = hikari.UNDEFINED, component: hikari.UndefinedNoneOr[hikari.api.ComponentBuilder] = hikari.UNDEFINED, @@ -289,12 +284,8 @@ async def edit_last_response( embed: hikari.UndefinedNoneOr[hikari.Embed] = hikari.UNDEFINED, embeds: hikari.UndefinedNoneOr[collections.Sequence[hikari.Embed]] = hikari.UNDEFINED, mentions_everyone: hikari.UndefinedOr[bool] = hikari.UNDEFINED, - user_mentions: typing.Union[ - hikari.SnowflakeishSequence[hikari.PartialUser], bool, hikari.UndefinedType - ] = hikari.UNDEFINED, - role_mentions: typing.Union[ - hikari.SnowflakeishSequence[hikari.PartialRole], bool, hikari.UndefinedType - ] = hikari.UNDEFINED, + user_mentions: hikari.SnowflakeishSequence[hikari.PartialUser] | bool | hikari.UndefinedType = hikari.UNDEFINED, + role_mentions: hikari.SnowflakeishSequence[hikari.PartialRole] | bool | hikari.UndefinedType = hikari.UNDEFINED, ) -> hikari.Message: # <>. delete_after = _delete_after_to_float(delete_after) if delete_after is not None else None @@ -348,7 +339,7 @@ async def respond( content: hikari.UndefinedOr[typing.Any] = hikari.UNDEFINED, *, ensure_result: bool = True, - delete_after: typing.Union[datetime.timedelta, float, int, None] = None, + delete_after: datetime.timedelta | float | int | None = None, attachment: hikari.UndefinedOr[hikari.Resourceish] = hikari.UNDEFINED, attachments: hikari.UndefinedOr[collections.Sequence[hikari.Resourceish]] = hikari.UNDEFINED, component: hikari.UndefinedOr[hikari.api.ComponentBuilder] = hikari.UNDEFINED, @@ -358,15 +349,11 @@ async def respond( sticker: hikari.UndefinedOr[hikari.SnowflakeishOr[hikari.PartialSticker]] = hikari.UNDEFINED, stickers: hikari.UndefinedOr[hikari.SnowflakeishSequence[hikari.PartialSticker]] = hikari.UNDEFINED, tts: hikari.UndefinedOr[bool] = hikari.UNDEFINED, - reply: typing.Union[bool, hikari.SnowflakeishOr[hikari.PartialMessage], hikari.UndefinedType] = False, + reply: bool | hikari.SnowflakeishOr[hikari.PartialMessage] | hikari.UndefinedType = False, mentions_everyone: hikari.UndefinedOr[bool] = hikari.UNDEFINED, mentions_reply: hikari.UndefinedOr[bool] = hikari.UNDEFINED, - user_mentions: typing.Union[ - hikari.SnowflakeishSequence[hikari.PartialUser], bool, hikari.UndefinedType - ] = hikari.UNDEFINED, - role_mentions: typing.Union[ - hikari.SnowflakeishSequence[hikari.PartialRole], bool, hikari.UndefinedType - ] = hikari.UNDEFINED, + user_mentions: hikari.SnowflakeishSequence[hikari.PartialUser] | bool | hikari.UndefinedType = hikari.UNDEFINED, + role_mentions: hikari.SnowflakeishSequence[hikari.PartialRole] | bool | hikari.UndefinedType = hikari.UNDEFINED, ) -> hikari.Message: # <>. delete_after = _delete_after_to_float(delete_after) if delete_after is not None else None diff --git a/tanjun/context/slash.py b/tanjun/context/slash.py index 9335162d7..84549104e 100644 --- a/tanjun/context/slash.py +++ b/tanjun/context/slash.py @@ -47,12 +47,13 @@ if typing.TYPE_CHECKING: from collections import abc as collections + from typing import Self - from typing_extensions import Self - - _ResponseTypeT = typing.Union[ - hikari.api.InteractionMessageBuilder, hikari.api.InteractionDeferredBuilder, hikari.api.InteractionModalBuilder - ] + _ResponseTypeT = ( + hikari.api.InteractionMessageBuilder + | hikari.api.InteractionDeferredBuilder + | hikari.api.InteractionModalBuilder + ) _T = typing.TypeVar("_T") _OtherT = typing.TypeVar("_OtherT") @@ -61,7 +62,7 @@ _LOGGER = logging.getLogger("hikari.tanjun.context") -def _delete_after_to_float(delete_after: typing.Union[datetime.timedelta, float, int], /) -> float: +def _delete_after_to_float(delete_after: datetime.timedelta | float | int, /) -> float: return delete_after.total_seconds() if isinstance(delete_after, datetime.timedelta) else float(delete_after) @@ -81,9 +82,7 @@ class SlashOption(tanjun.SlashOption): __slots__ = ("_option", "_resolved") - def __init__( - self, resolved: typing.Optional[hikari.ResolvedOptionData], option: hikari.CommandInteractionOption, / - ): + def __init__(self, resolved: hikari.ResolvedOptionData | None, option: hikari.CommandInteractionOption, /): """Initialise a slash option. Parameters @@ -105,12 +104,12 @@ def name(self) -> str: return self._option.name @property - def type(self) -> typing.Union[hikari.OptionType, int]: + def type(self) -> hikari.OptionType | int: # <>. return self._option.type @property - def value(self) -> typing.Union[str, int, hikari.Snowflake, bool, float]: + def value(self) -> str | int | hikari.Snowflake | bool | float: # <>. # This is asserted in __init__ assert self._option.value is not None @@ -159,7 +158,7 @@ def string(self) -> str: def resolve_value( self, - ) -> typing.Union[hikari.Attachment, hikari.InteractionChannel, hikari.InteractionMember, hikari.Role, hikari.User]: + ) -> hikari.Attachment | hikari.InteractionChannel | hikari.InteractionMember | hikari.Role | hikari.User: # <>. if self._option.type is hikari.OptionType.CHANNEL: return self.resolve_to_channel() @@ -201,11 +200,11 @@ def resolve_to_channel(self) -> hikari.InteractionChannel: def resolve_to_member(self) -> hikari.InteractionMember: ... @typing.overload - def resolve_to_member(self, *, default: _T) -> typing.Union[hikari.InteractionMember, _T]: ... + def resolve_to_member(self, *, default: _T) -> hikari.InteractionMember | _T: ... def resolve_to_member( - self, *, default: typing.Union[_T, _internal.Default] = _internal.DEFAULT - ) -> typing.Union[hikari.InteractionMember, _T]: + self, *, default: _T | _internal.Default = _internal.DEFAULT + ) -> hikari.InteractionMember | _T: # <>. # What does self.value being None mean? if self._option.type is hikari.OptionType.USER: @@ -234,7 +233,7 @@ def resolve_to_member( raise TypeError(f"Cannot resolve non-user option type {self._option.type} to a member") - def resolve_to_mentionable(self) -> typing.Union[hikari.Role, hikari.User, hikari.Member]: + def resolve_to_mentionable(self) -> hikari.Role | hikari.User | hikari.Member: # <>. if self._option.type is hikari.OptionType.MENTIONABLE: assert self._option.value is not None @@ -267,7 +266,7 @@ def resolve_to_role(self) -> hikari.Role: raise TypeError(f"Cannot resolve non-role option type {self._option.type} to a role") - def resolve_to_user(self) -> typing.Union[hikari.User, hikari.Member]: + def resolve_to_user(self) -> hikari.User | hikari.Member: # <>. if self._option.type is hikari.OptionType.USER: assert self._option.value is not None @@ -306,15 +305,15 @@ def __init__( register_task: collections.Callable[[asyncio.Task[typing.Any]], None], *, default_to_ephemeral: bool = False, - future: typing.Optional[asyncio.Future[_ResponseTypeT]] = None, + future: asyncio.Future[_ResponseTypeT] | None = None, ) -> None: super().__init__(client) self._defaults_to_ephemeral = default_to_ephemeral - self._defer_task: typing.Optional[asyncio.Task[None]] = None + self._defer_task: asyncio.Task[None] | None = None self._has_been_deferred = False self._has_responded = False self._interaction = interaction - self._last_response_id: typing.Optional[hikari.Snowflake] = None + self._last_response_id: hikari.Snowflake | None = None self._register_task = register_task self._response_future = future self._response_lock = asyncio.Lock() @@ -351,7 +350,7 @@ def expires_at(self) -> datetime.datetime: return self.created_at + _INTERACTION_LIFETIME @property - def guild_id(self) -> typing.Optional[hikari.Snowflake]: + def guild_id(self) -> hikari.Snowflake | None: # <>. return self._interaction.guild_id @@ -371,7 +370,7 @@ def is_human(self) -> typing.Literal[True]: return True @property - def member(self) -> typing.Optional[hikari.InteractionMember]: + def member(self) -> hikari.InteractionMember | None: # <>. return self._interaction.member @@ -380,7 +379,7 @@ def interaction(self) -> hikari.CommandInteraction: # <>. return self._interaction - async def _auto_defer(self, countdown: typing.Union[int, float], /) -> None: + async def _auto_defer(self, countdown: int | float, /) -> None: await asyncio.sleep(countdown) await self.defer() @@ -391,11 +390,11 @@ def cancel_defer(self) -> None: def _get_flags( self, - flags: typing.Union[hikari.UndefinedType, int, hikari.MessageFlag] = hikari.UNDEFINED, + flags: hikari.UndefinedType | int | hikari.MessageFlag = hikari.UNDEFINED, /, *, - ephemeral: typing.Optional[bool] = None, - ) -> typing.Union[int, hikari.MessageFlag]: + ephemeral: bool | None = None, + ) -> int | hikari.MessageFlag: if flags is hikari.UNDEFINED: if ephemeral is True or (ephemeral is None and self._defaults_to_ephemeral): return hikari.MessageFlag.EPHEMERAL @@ -410,7 +409,7 @@ def _get_flags( return flags - def start_defer_timer(self, count_down: typing.Union[int, float], /) -> Self: + def start_defer_timer(self, count_down: int | float, /) -> Self: """Start the auto-deferral timer. Parameters @@ -440,8 +439,8 @@ def set_ephemeral_default(self, state: bool, /) -> Self: async def defer( self, *, - flags: typing.Union[hikari.UndefinedType, int, hikari.MessageFlag] = hikari.UNDEFINED, - ephemeral: typing.Optional[bool] = None, + flags: hikari.UndefinedType | int | hikari.MessageFlag = hikari.UNDEFINED, + ephemeral: bool | None = None, ) -> None: # <>. flags = self._get_flags(flags, ephemeral=ephemeral) @@ -465,7 +464,7 @@ async def defer( hikari.ResponseType.DEFERRED_MESSAGE_CREATE, flags=flags ) - def _validate_delete_after(self, delete_after: typing.Union[float, int, datetime.timedelta], /) -> float: + def _validate_delete_after(self, delete_after: float | int | datetime.timedelta, /) -> float: delete_after = _delete_after_to_float(delete_after) time_left = ( _INTERACTION_LIFETIME - (datetime.datetime.now(tz=datetime.timezone.utc) - self.created_at) @@ -486,8 +485,8 @@ async def _create_followup( self, content: hikari.UndefinedOr[typing.Any] = hikari.UNDEFINED, *, - delete_after: typing.Union[datetime.timedelta, float, int, None] = None, - ephemeral: typing.Optional[bool] = None, + delete_after: datetime.timedelta | float | int | None = None, + ephemeral: bool | None = None, attachment: hikari.UndefinedOr[hikari.Resourceish] = hikari.UNDEFINED, attachments: hikari.UndefinedOr[collections.Sequence[hikari.Resourceish]] = hikari.UNDEFINED, component: hikari.UndefinedOr[hikari.api.ComponentBuilder] = hikari.UNDEFINED, @@ -495,14 +494,10 @@ async def _create_followup( embed: hikari.UndefinedOr[hikari.Embed] = hikari.UNDEFINED, embeds: hikari.UndefinedOr[collections.Sequence[hikari.Embed]] = hikari.UNDEFINED, mentions_everyone: hikari.UndefinedOr[bool] = hikari.UNDEFINED, - user_mentions: typing.Union[ - hikari.SnowflakeishSequence[hikari.PartialUser], bool, hikari.UndefinedType - ] = hikari.UNDEFINED, - role_mentions: typing.Union[ - hikari.SnowflakeishSequence[hikari.PartialRole], bool, hikari.UndefinedType - ] = hikari.UNDEFINED, + user_mentions: hikari.SnowflakeishSequence[hikari.PartialUser] | bool | hikari.UndefinedType = hikari.UNDEFINED, + role_mentions: hikari.SnowflakeishSequence[hikari.PartialRole] | bool | hikari.UndefinedType = hikari.UNDEFINED, tts: hikari.UndefinedOr[bool] = hikari.UNDEFINED, - flags: typing.Union[hikari.UndefinedType, int, hikari.MessageFlag] = hikari.UNDEFINED, + flags: hikari.UndefinedType | int | hikari.MessageFlag = hikari.UNDEFINED, ) -> hikari.Message: delete_after = self._validate_delete_after(delete_after) if delete_after is not None else None message = await self._interaction.execute( @@ -535,8 +530,8 @@ async def create_followup( self, content: hikari.UndefinedOr[typing.Any] = hikari.UNDEFINED, *, - delete_after: typing.Union[datetime.timedelta, float, int, None] = None, - ephemeral: typing.Optional[bool] = None, + delete_after: datetime.timedelta | float | int | None = None, + ephemeral: bool | None = None, attachment: hikari.UndefinedOr[hikari.Resourceish] = hikari.UNDEFINED, attachments: hikari.UndefinedOr[collections.Sequence[hikari.Resourceish]] = hikari.UNDEFINED, component: hikari.UndefinedOr[hikari.api.ComponentBuilder] = hikari.UNDEFINED, @@ -544,14 +539,10 @@ async def create_followup( embed: hikari.UndefinedOr[hikari.Embed] = hikari.UNDEFINED, embeds: hikari.UndefinedOr[collections.Sequence[hikari.Embed]] = hikari.UNDEFINED, mentions_everyone: hikari.UndefinedOr[bool] = hikari.UNDEFINED, - user_mentions: typing.Union[ - hikari.SnowflakeishSequence[hikari.PartialUser], bool, hikari.UndefinedType - ] = hikari.UNDEFINED, - role_mentions: typing.Union[ - hikari.SnowflakeishSequence[hikari.PartialRole], bool, hikari.UndefinedType - ] = hikari.UNDEFINED, + user_mentions: hikari.SnowflakeishSequence[hikari.PartialUser] | bool | hikari.UndefinedType = hikari.UNDEFINED, + role_mentions: hikari.SnowflakeishSequence[hikari.PartialRole] | bool | hikari.UndefinedType = hikari.UNDEFINED, tts: hikari.UndefinedOr[bool] = hikari.UNDEFINED, - flags: typing.Union[hikari.UndefinedType, int, hikari.MessageFlag] = hikari.UNDEFINED, + flags: hikari.UndefinedType | int | hikari.MessageFlag = hikari.UNDEFINED, ) -> hikari.Message: # <>. async with self._response_lock: @@ -583,8 +574,8 @@ async def _create_initial_response( self, content: hikari.UndefinedOr[typing.Any] = hikari.UNDEFINED, *, - delete_after: typing.Union[datetime.timedelta, float, int, None] = None, - ephemeral: typing.Optional[bool] = None, + delete_after: datetime.timedelta | float | int | None = None, + ephemeral: bool | None = None, attachment: hikari.UndefinedOr[hikari.Resourceish] = hikari.UNDEFINED, attachments: hikari.UndefinedOr[collections.Sequence[hikari.Resourceish]] = hikari.UNDEFINED, component: hikari.UndefinedOr[hikari.api.ComponentBuilder] = hikari.UNDEFINED, @@ -592,13 +583,9 @@ async def _create_initial_response( embed: hikari.UndefinedOr[hikari.Embed] = hikari.UNDEFINED, embeds: hikari.UndefinedOr[collections.Sequence[hikari.Embed]] = hikari.UNDEFINED, mentions_everyone: hikari.UndefinedOr[bool] = hikari.UNDEFINED, - user_mentions: typing.Union[ - hikari.SnowflakeishSequence[hikari.PartialUser], bool, hikari.UndefinedType - ] = hikari.UNDEFINED, - role_mentions: typing.Union[ - hikari.SnowflakeishSequence[hikari.PartialRole], bool, hikari.UndefinedType - ] = hikari.UNDEFINED, - flags: typing.Union[int, hikari.MessageFlag, hikari.UndefinedType] = hikari.UNDEFINED, + user_mentions: hikari.SnowflakeishSequence[hikari.PartialUser] | bool | hikari.UndefinedType = hikari.UNDEFINED, + role_mentions: hikari.SnowflakeishSequence[hikari.PartialRole] | bool | hikari.UndefinedType = hikari.UNDEFINED, + flags: int | hikari.MessageFlag | hikari.UndefinedType = hikari.UNDEFINED, tts: hikari.UndefinedOr[bool] = hikari.UNDEFINED, ) -> None: delete_after = self._validate_delete_after(delete_after) if delete_after is not None else None @@ -659,8 +646,8 @@ async def create_initial_response( self, content: hikari.UndefinedOr[typing.Any] = hikari.UNDEFINED, *, - delete_after: typing.Union[datetime.timedelta, float, int, None] = None, - ephemeral: typing.Optional[bool] = None, + delete_after: datetime.timedelta | float | int | None = None, + ephemeral: bool | None = None, attachment: hikari.UndefinedOr[hikari.Resourceish] = hikari.UNDEFINED, attachments: hikari.UndefinedOr[collections.Sequence[hikari.Resourceish]] = hikari.UNDEFINED, component: hikari.UndefinedOr[hikari.api.ComponentBuilder] = hikari.UNDEFINED, @@ -668,13 +655,9 @@ async def create_initial_response( embed: hikari.UndefinedOr[hikari.Embed] = hikari.UNDEFINED, embeds: hikari.UndefinedOr[collections.Sequence[hikari.Embed]] = hikari.UNDEFINED, mentions_everyone: hikari.UndefinedOr[bool] = hikari.UNDEFINED, - user_mentions: typing.Union[ - hikari.SnowflakeishSequence[hikari.PartialUser], bool, hikari.UndefinedType - ] = hikari.UNDEFINED, - role_mentions: typing.Union[ - hikari.SnowflakeishSequence[hikari.PartialRole], bool, hikari.UndefinedType - ] = hikari.UNDEFINED, - flags: typing.Union[int, hikari.MessageFlag, hikari.UndefinedType] = hikari.UNDEFINED, + user_mentions: hikari.SnowflakeishSequence[hikari.PartialUser] | bool | hikari.UndefinedType = hikari.UNDEFINED, + role_mentions: hikari.SnowflakeishSequence[hikari.PartialRole] | bool | hikari.UndefinedType = hikari.UNDEFINED, + flags: int | hikari.MessageFlag | hikari.UndefinedType = hikari.UNDEFINED, tts: hikari.UndefinedOr[bool] = hikari.UNDEFINED, ) -> None: # <>. @@ -721,7 +704,7 @@ async def edit_initial_response( self, content: hikari.UndefinedOr[typing.Any] = hikari.UNDEFINED, *, - delete_after: typing.Union[datetime.timedelta, float, int, None] = None, + delete_after: datetime.timedelta | float | int | None = None, attachment: hikari.UndefinedNoneOr[hikari.Resourceish] = hikari.UNDEFINED, attachments: hikari.UndefinedNoneOr[collections.Sequence[hikari.Resourceish]] = hikari.UNDEFINED, component: hikari.UndefinedNoneOr[hikari.api.ComponentBuilder] = hikari.UNDEFINED, @@ -729,12 +712,8 @@ async def edit_initial_response( embed: hikari.UndefinedNoneOr[hikari.Embed] = hikari.UNDEFINED, embeds: hikari.UndefinedNoneOr[collections.Sequence[hikari.Embed]] = hikari.UNDEFINED, mentions_everyone: hikari.UndefinedOr[bool] = hikari.UNDEFINED, - user_mentions: typing.Union[ - hikari.SnowflakeishSequence[hikari.PartialUser], bool, hikari.UndefinedType - ] = hikari.UNDEFINED, - role_mentions: typing.Union[ - hikari.SnowflakeishSequence[hikari.PartialRole], bool, hikari.UndefinedType - ] = hikari.UNDEFINED, + user_mentions: hikari.SnowflakeishSequence[hikari.PartialUser] | bool | hikari.UndefinedType = hikari.UNDEFINED, + role_mentions: hikari.SnowflakeishSequence[hikari.PartialRole] | bool | hikari.UndefinedType = hikari.UNDEFINED, ) -> hikari.Message: # <>. delete_after = self._validate_delete_after(delete_after) if delete_after is not None else None @@ -762,7 +741,7 @@ async def edit_last_response( self, content: hikari.UndefinedOr[typing.Any] = hikari.UNDEFINED, *, - delete_after: typing.Union[datetime.timedelta, float, int, None] = None, + delete_after: datetime.timedelta | float | int | None = None, attachment: hikari.UndefinedNoneOr[hikari.Resourceish] = hikari.UNDEFINED, attachments: hikari.UndefinedNoneOr[collections.Sequence[hikari.Resourceish]] = hikari.UNDEFINED, component: hikari.UndefinedNoneOr[hikari.api.ComponentBuilder] = hikari.UNDEFINED, @@ -770,12 +749,8 @@ async def edit_last_response( embed: hikari.UndefinedNoneOr[hikari.Embed] = hikari.UNDEFINED, embeds: hikari.UndefinedNoneOr[collections.Sequence[hikari.Embed]] = hikari.UNDEFINED, mentions_everyone: hikari.UndefinedOr[bool] = hikari.UNDEFINED, - user_mentions: typing.Union[ - hikari.SnowflakeishSequence[hikari.PartialUser], bool, hikari.UndefinedType - ] = hikari.UNDEFINED, - role_mentions: typing.Union[ - hikari.SnowflakeishSequence[hikari.PartialRole], bool, hikari.UndefinedType - ] = hikari.UNDEFINED, + user_mentions: hikari.SnowflakeishSequence[hikari.PartialUser] | bool | hikari.UndefinedType = hikari.UNDEFINED, + role_mentions: hikari.SnowflakeishSequence[hikari.PartialRole] | bool | hikari.UndefinedType = hikari.UNDEFINED, ) -> hikari.Message: # <>. if self._last_response_id: @@ -862,7 +837,7 @@ async def respond( content: hikari.UndefinedOr[typing.Any] = hikari.UNDEFINED, *, ensure_result: typing.Literal[True], - delete_after: typing.Union[datetime.timedelta, float, int, None] = None, + delete_after: datetime.timedelta | float | int | None = None, attachment: hikari.UndefinedOr[hikari.Resourceish] = hikari.UNDEFINED, attachments: hikari.UndefinedOr[collections.Sequence[hikari.Resourceish]] = hikari.UNDEFINED, component: hikari.UndefinedOr[hikari.api.ComponentBuilder] = hikari.UNDEFINED, @@ -870,12 +845,8 @@ async def respond( embed: hikari.UndefinedOr[hikari.Embed] = hikari.UNDEFINED, embeds: hikari.UndefinedOr[collections.Sequence[hikari.Embed]] = hikari.UNDEFINED, mentions_everyone: hikari.UndefinedOr[bool] = hikari.UNDEFINED, - user_mentions: typing.Union[ - hikari.SnowflakeishSequence[hikari.PartialUser], bool, hikari.UndefinedType - ] = hikari.UNDEFINED, - role_mentions: typing.Union[ - hikari.SnowflakeishSequence[hikari.PartialRole], bool, hikari.UndefinedType - ] = hikari.UNDEFINED, + user_mentions: hikari.SnowflakeishSequence[hikari.PartialUser] | bool | hikari.UndefinedType = hikari.UNDEFINED, + role_mentions: hikari.SnowflakeishSequence[hikari.PartialRole] | bool | hikari.UndefinedType = hikari.UNDEFINED, ) -> hikari.Message: ... @typing.overload @@ -884,7 +855,7 @@ async def respond( content: hikari.UndefinedOr[typing.Any] = hikari.UNDEFINED, *, ensure_result: bool = False, - delete_after: typing.Union[datetime.timedelta, float, int, None] = None, + delete_after: datetime.timedelta | float | int | None = None, attachment: hikari.UndefinedOr[hikari.Resourceish] = hikari.UNDEFINED, attachments: hikari.UndefinedOr[collections.Sequence[hikari.Resourceish]] = hikari.UNDEFINED, component: hikari.UndefinedOr[hikari.api.ComponentBuilder] = hikari.UNDEFINED, @@ -892,20 +863,16 @@ async def respond( embed: hikari.UndefinedOr[hikari.Embed] = hikari.UNDEFINED, embeds: hikari.UndefinedOr[collections.Sequence[hikari.Embed]] = hikari.UNDEFINED, mentions_everyone: hikari.UndefinedOr[bool] = hikari.UNDEFINED, - user_mentions: typing.Union[ - hikari.SnowflakeishSequence[hikari.PartialUser], bool, hikari.UndefinedType - ] = hikari.UNDEFINED, - role_mentions: typing.Union[ - hikari.SnowflakeishSequence[hikari.PartialRole], bool, hikari.UndefinedType - ] = hikari.UNDEFINED, - ) -> typing.Optional[hikari.Message]: ... + user_mentions: hikari.SnowflakeishSequence[hikari.PartialUser] | bool | hikari.UndefinedType = hikari.UNDEFINED, + role_mentions: hikari.SnowflakeishSequence[hikari.PartialRole] | bool | hikari.UndefinedType = hikari.UNDEFINED, + ) -> hikari.Message | None: ... async def respond( self, content: hikari.UndefinedOr[typing.Any] = hikari.UNDEFINED, *, ensure_result: bool = False, - delete_after: typing.Union[datetime.timedelta, float, int, None] = None, + delete_after: datetime.timedelta | float | int | None = None, attachment: hikari.UndefinedOr[hikari.Resourceish] = hikari.UNDEFINED, attachments: hikari.UndefinedOr[collections.Sequence[hikari.Resourceish]] = hikari.UNDEFINED, component: hikari.UndefinedOr[hikari.api.ComponentBuilder] = hikari.UNDEFINED, @@ -913,13 +880,9 @@ async def respond( embed: hikari.UndefinedOr[hikari.Embed] = hikari.UNDEFINED, embeds: hikari.UndefinedOr[collections.Sequence[hikari.Embed]] = hikari.UNDEFINED, mentions_everyone: hikari.UndefinedOr[bool] = hikari.UNDEFINED, - user_mentions: typing.Union[ - hikari.SnowflakeishSequence[hikari.PartialUser], bool, hikari.UndefinedType - ] = hikari.UNDEFINED, - role_mentions: typing.Union[ - hikari.SnowflakeishSequence[hikari.PartialRole], bool, hikari.UndefinedType - ] = hikari.UNDEFINED, - ) -> typing.Optional[hikari.Message]: + user_mentions: hikari.SnowflakeishSequence[hikari.PartialUser] | bool | hikari.UndefinedType = hikari.UNDEFINED, + role_mentions: hikari.SnowflakeishSequence[hikari.PartialRole] | bool | hikari.UndefinedType = hikari.UNDEFINED, + ) -> hikari.Message | None: # <>. async with self._response_lock: if self._has_responded: @@ -979,7 +942,7 @@ def _to_list( singular: hikari.UndefinedOr[_T], plural: hikari.UndefinedOr[collections.Sequence[_T]], other: _OtherT, - type_: typing.Union[type[_T], tuple[type[_T], ...]], + type_: type[_T] | tuple[type[_T], ...], name: str, /, ) -> tuple[hikari.UndefinedOr[list[_T]], hikari.UndefinedOr[_OtherT]]: @@ -1010,8 +973,8 @@ def __init__( register_task: collections.Callable[[asyncio.Task[typing.Any]], None], *, default_to_ephemeral: bool = False, - future: typing.Optional[asyncio.Future[_ResponseTypeT]] = None, - on_not_found: typing.Optional[collections.Callable[[tanjun.SlashContext], collections.Awaitable[None]]] = None, + future: asyncio.Future[_ResponseTypeT] | None = None, + on_not_found: collections.Callable[[tanjun.SlashContext], collections.Awaitable[None]] | None = None, ) -> None: """Initialise a slash command context. @@ -1035,14 +998,14 @@ def __init__( self._marked_not_found = False self._on_not_found = on_not_found - self._command: typing.Optional[tanjun.BaseSlashCommand] = None + self._command: tanjun.BaseSlashCommand | None = None command_name, options = _internal.flatten_options(interaction.command_name, interaction.options) self._command_name = command_name self._options = {option.name: SlashOption(interaction.resolved, option) for option in options} (self._set_type_special_case(tanjun.SlashContext, self)._set_type_special_case(SlashContext, self)) @property - def command(self) -> typing.Optional[tanjun.BaseSlashCommand]: + def command(self) -> tanjun.BaseSlashCommand | None: # <>. return self._command @@ -1068,7 +1031,7 @@ async def mark_not_found(self) -> None: self._marked_not_found = True await self._on_not_found(self) - def set_command(self, command: typing.Optional[tanjun.BaseSlashCommand], /) -> Self: + def set_command(self, command: tanjun.BaseSlashCommand | None, /) -> Self: # <>. self._assert_not_final() if command: diff --git a/tanjun/conversion.py b/tanjun/conversion.py index 769185ad1..778c409f7 100644 --- a/tanjun/conversion.py +++ b/tanjun/conversion.py @@ -96,7 +96,7 @@ _PartialChannelT = typing.TypeVar("_PartialChannelT", bound=hikari.PartialChannel) -_SnowflakeIsh = typing.Union[str, int] +_SnowflakeIsh = str | int _ValueT = typing.TypeVar("_ValueT") _LOGGER = logging.getLogger("hikari.tanjun.conversion") @@ -246,7 +246,7 @@ class ToChannel(BaseConverter): def __init__( self, *, - allowed_types: typing.Optional[collections.Collection[typing.Union[type[hikari.PartialChannel], int]]] = None, + allowed_types: collections.Collection[type[hikari.PartialChannel] | int] | None = None, include_dms: bool = True, ) -> None: """Initialise a to channel converter. @@ -334,9 +334,9 @@ async def __call__( /, ctx: alluka.Injected[tanjun.Context], *, - cache: alluka.Injected[typing.Optional[_GuildChannelCacheT]] = None, - dm_cache: alluka.Injected[typing.Optional[_DmCacheT]] = None, - thread_cache: alluka.Injected[typing.Optional[_ThreadCacheT]] = None, + cache: alluka.Injected[_GuildChannelCacheT | None] = None, + dm_cache: alluka.Injected[_DmCacheT | None] = None, + thread_cache: alluka.Injected[_ThreadCacheT | None] = None, ) -> hikari.PartialChannel: channel_id = parse_channel_id(argument, message="No valid channel mention or ID found") if ctx.cache and (channel_ := ctx.cache.get_guild_channel(channel_id)): @@ -427,7 +427,7 @@ async def __call__( /, ctx: alluka.Injected[tanjun.Context], *, - cache: alluka.Injected[typing.Optional[_EmojiCacheT]] = None, + cache: alluka.Injected[_EmojiCacheT | None] = None, ) -> hikari.KnownCustomEmoji: emoji_id = parse_emoji_id(argument, message="No valid emoji or emoji ID found") @@ -483,7 +483,7 @@ async def __call__( /, ctx: alluka.Injected[tanjun.Context], *, - cache: alluka.Injected[typing.Optional[_GuildCacheT]] = None, + cache: alluka.Injected[_GuildCacheT | None] = None, ) -> hikari.Guild: guild_id = parse_snowflake(argument, message="No valid guild ID found") if ctx.cache and (guild := ctx.cache.get_guild(guild_id)): @@ -534,7 +534,7 @@ async def __call__( /, ctx: alluka.Injected[tanjun.Context], *, - cache: alluka.Injected[typing.Optional[_InviteCacheT]] = None, + cache: alluka.Injected[_InviteCacheT | None] = None, ) -> hikari.Invite: if ctx.cache and (invite := ctx.cache.get_invite(argument)): return invite @@ -593,7 +593,7 @@ async def __call__( /, ctx: alluka.Injected[tanjun.Context], *, - cache: alluka.Injected[typing.Optional[_InviteCacheT]] = None, + cache: alluka.Injected[_InviteCacheT | None] = None, ) -> hikari.InviteWithMetadata: if ctx.cache and (invite := ctx.cache.get_invite(argument)): return invite @@ -640,7 +640,7 @@ async def __call__( /, ctx: alluka.Injected[tanjun.Context], *, - cache: alluka.Injected[typing.Optional[_MemberCacheT]] = None, + cache: alluka.Injected[_MemberCacheT | None] = None, ) -> hikari.Member: if ctx.guild_id is None: raise ValueError("Cannot get a member from a DM channel") @@ -721,7 +721,7 @@ async def __call__( /, ctx: alluka.Injected[tanjun.Context], *, - cache: alluka.Injected[typing.Optional[_PresenceCacheT]] = None, + cache: alluka.Injected[_PresenceCacheT | None] = None, ) -> hikari.MemberPresence: if ctx.guild_id is None: raise ValueError("Cannot get a presence from a DM channel") @@ -766,7 +766,7 @@ async def __call__( /, ctx: alluka.Injected[tanjun.Context], *, - cache: alluka.Injected[typing.Optional[_RoleCacheT]] = None, + cache: alluka.Injected[_RoleCacheT | None] = None, ) -> hikari.Role: role_id = parse_role_id(argument, message="No valid role mention or ID found") if ctx.cache and (role := ctx.cache.get_role(role_id)): @@ -819,7 +819,7 @@ async def __call__( /, ctx: alluka.Injected[tanjun.Context], *, - cache: alluka.Injected[typing.Optional[_UserCacheT]] = None, + cache: alluka.Injected[_UserCacheT | None] = None, ) -> hikari.User: # TODO: search by name if this is a guild context user_id = parse_user_id(argument, message="No valid user mention or ID found") @@ -880,7 +880,7 @@ async def __call__( /, ctx: alluka.Injected[tanjun.Context], *, - cache: alluka.Injected[typing.Optional[_MessageCacheT]] = None, + cache: alluka.Injected[_MessageCacheT | None] = None, ) -> hikari.Message: channel_id, message_id = parse_message_id(argument) if ctx.cache and (message := ctx.cache.get_message(message_id)): @@ -941,7 +941,7 @@ async def __call__( /, ctx: alluka.Injected[tanjun.Context], *, - cache: alluka.Injected[typing.Optional[_VoiceStateCacheT]] = None, + cache: alluka.Injected[_VoiceStateCacheT | None] = None, ) -> hikari.VoiceState: if ctx.guild_id is None: raise ValueError("Cannot get a voice state from a DM channel") @@ -995,7 +995,7 @@ def parse(value: _SnowflakeIsh, /, *, message: str = "No valid mention or ID fou ValueError If the value cannot be parsed. """ - result: typing.Optional[hikari.Snowflake] = None + result: hikari.Snowflake | None = None if isinstance(value, int) or value.isdigit(): result = hikari.Snowflake(value) @@ -1249,7 +1249,7 @@ def parse(value: _SnowflakeIsh, /) -> list[hikari.Snowflake]: def parse_message_id( value: _SnowflakeIsh, /, *, message: str = "No valid message link or ID found" -) -> tuple[typing.Optional[hikari.Snowflake], hikari.Snowflake]: +) -> tuple[hikari.Snowflake | None, hikari.Snowflake]: """Parse a user ID from a string or int value. Parameters @@ -1269,8 +1269,8 @@ def parse_message_id( ValueError If the value cannot be parsed. """ - channel_id: typing.Optional[hikari.Snowflake] = None - message_id: typing.Optional[hikari.Snowflake] = None + channel_id: hikari.Snowflake | None = None + message_id: hikari.Snowflake | None = None if isinstance(value, int) or value.isdigit(): message_id = hikari.Snowflake(value) @@ -1420,7 +1420,7 @@ def from_datetime(value: datetime.timedelta, /) -> str: ... def from_datetime(value: datetime.datetime, /, *, style: str = "f") -> str: ... -def from_datetime(value: typing.Union[datetime.datetime, datetime.timedelta], /, *, style: str = "f") -> str: +def from_datetime(value: datetime.datetime | datetime.timedelta, /, *, style: str = "f") -> str: """Format a datetime as Discord's datetime format. More information on this format can be found at diff --git a/tanjun/dependencies/async_cache.py b/tanjun/dependencies/async_cache.py index d9f55ab12..6b4507994 100644 --- a/tanjun/dependencies/async_cache.py +++ b/tanjun/dependencies/async_cache.py @@ -142,7 +142,7 @@ class SingleStoreCache(abc.ABC, typing.Generic[_ValueT]): __slots__ = () @abc.abstractmethod - async def get(self, *, default: _DefaultT = ...) -> typing.Union[_ValueT, _DefaultT]: + async def get(self, *, default: _DefaultT = ...) -> _ValueT | _DefaultT: """Get the entry. Parameters @@ -187,7 +187,7 @@ class AsyncCache(abc.ABC, typing.Generic[_KeyT, _ValueT]): __slots__ = () @abc.abstractmethod - async def get(self, key: _KeyT, /, *, default: _DefaultT = ...) -> typing.Union[_ValueT, _DefaultT]: + async def get(self, key: _KeyT, /, *, default: _DefaultT = ...) -> _ValueT | _DefaultT: """Get an entry from this cache by ID. Parameters @@ -247,7 +247,7 @@ class ChannelBoundCache(abc.ABC, typing.Generic[_KeyT, _ValueT]): @abc.abstractmethod async def get_from_channel( self, channel_id: hikari.Snowflakeish, key: _KeyT, /, *, default: _DefaultT = ... - ) -> typing.Union[_ValueT, _DefaultT]: + ) -> _ValueT | _DefaultT: """Get an entry from this cache for a specific channel by ID. Parameters @@ -324,7 +324,7 @@ class GuildBoundCache(abc.ABC, typing.Generic[_KeyT, _ValueT]): @abc.abstractmethod async def get_from_guild( self, guild_id: hikari.Snowflakeish, key: _KeyT, /, *, default: _DefaultT = ... - ) -> typing.Union[_ValueT, _DefaultT]: + ) -> _ValueT | _DefaultT: """Get an entry from this cache for a specific guild by ID. Parameters diff --git a/tanjun/dependencies/callbacks.py b/tanjun/dependencies/callbacks.py index fcab4a920..26ed0c271 100644 --- a/tanjun/dependencies/callbacks.py +++ b/tanjun/dependencies/callbacks.py @@ -33,8 +33,6 @@ __all__: list[str] = ["fetch_my_user"] -import typing - import alluka import hikari @@ -45,7 +43,7 @@ async def fetch_my_user( client: alluka.Injected[tanjun.Client], *, - me_cache: alluka.Injected[typing.Optional[async_cache.SingleStoreCache[hikari.OwnUser]]] = None, + me_cache: alluka.Injected[async_cache.SingleStoreCache[hikari.OwnUser] | None] = None, ) -> hikari.OwnUser: """Fetch the current user from the client's cache or rest client. diff --git a/tanjun/dependencies/data.py b/tanjun/dependencies/data.py index e1aa472be..2c34bedca 100644 --- a/tanjun/dependencies/data.py +++ b/tanjun/dependencies/data.py @@ -45,8 +45,7 @@ if typing.TYPE_CHECKING: import contextlib from collections import abc as collections - - from typing_extensions import Self + from typing import Self _T = typing.TypeVar("_T") @@ -71,15 +70,15 @@ def __init__(self, callback: alluka.abc.CallbackSig[_T], /) -> None: This supports dependency injection and may either be sync or asynchronous. """ self._callback = callback - self._lock: typing.Optional[asyncio.Lock] = None - self._value: typing.Optional[_T] = None + self._lock: asyncio.Lock | None = None + self._value: _T | None = None @property def callback(self) -> alluka.abc.CallbackSig[_T]: """Descriptor of the callback used to get this constant's initial value.""" return self._callback - def get_value(self) -> typing.Optional[_T]: + def get_value(self) -> _T | None: """Get the value of this constant if set, else [None][].""" return self._value @@ -225,16 +224,12 @@ class _CacheCallback(typing.Generic[_T]): __slots__ = ("_callback", "_expire_after", "_last_called", "_lock", "_result", "__weakref__") def __init__( - self, - callback: alluka.abc.CallbackSig[_T], - /, - *, - expire_after: typing.Union[int, float, datetime.timedelta, None], + self, callback: alluka.abc.CallbackSig[_T], /, *, expire_after: int | float | datetime.timedelta | None ) -> None: self._callback = callback - self._last_called: typing.Optional[float] = None - self._lock: typing.Optional[asyncio.Lock] = None - self._result: typing.Union[_T, tanjun.NoDefault] = tanjun.NO_DEFAULT + self._last_called: float | None = None + self._lock: asyncio.Lock | None = None + self._result: _T | tanjun.NoDefault = tanjun.NO_DEFAULT if expire_after is None: pass elif isinstance(expire_after, datetime.timedelta): @@ -274,7 +269,7 @@ async def __call__(self, *args: typing.Any, ctx: alluka.Injected[alluka.abc.Cont def cache_callback( - callback: alluka.abc.CallbackSig[_T], /, *, expire_after: typing.Union[int, float, datetime.timedelta, None] = None + callback: alluka.abc.CallbackSig[_T], /, *, expire_after: int | float | datetime.timedelta | None = None ) -> collections.Callable[..., collections.Coroutine[typing.Any, typing.Any, _T]]: """Cache the result of a callback within a dependency injection context. @@ -306,7 +301,7 @@ def cache_callback( def cached_inject( - callback: alluka.abc.CallbackSig[_T], /, *, expire_after: typing.Union[float, int, datetime.timedelta, None] = None + callback: alluka.abc.CallbackSig[_T], /, *, expire_after: float | int | datetime.timedelta | None = None ) -> _T: """Inject a callback with caching. diff --git a/tanjun/dependencies/limiters.py b/tanjun/dependencies/limiters.py index fe7f013ab..485a57be7 100644 --- a/tanjun/dependencies/limiters.py +++ b/tanjun/dependencies/limiters.py @@ -78,8 +78,7 @@ import contextlib import types from collections import abc as collections - - from typing_extensions import Self + from typing import Self _CommandT = typing.TypeVar("_CommandT", bound=tanjun.ExecutableCommand[typing.Any]) _InnerResourceSig = collections.Callable[[], "_InnerResourceT"] @@ -103,10 +102,10 @@ class ResourceNotTracked(Exception): class CooldownDepleted(ResourceDepleted): """Raised when a cooldown bucket is already depleted.""" - wait_until: typing.Optional[datetime.datetime] + wait_until: datetime.datetime | None """When this resource will next be available, if known.""" - def __init__(self, wait_until: typing.Optional[datetime.datetime], /) -> None: + def __init__(self, wait_until: datetime.datetime | None, /) -> None: self.wait_until = wait_until @@ -119,7 +118,7 @@ class AbstractCooldownManager(abc.ABC): @abc.abstractmethod async def check_cooldown( self, bucket_id: str, ctx: tanjun.Context, /, *, increment: bool = False - ) -> typing.Optional[datetime.datetime]: + ) -> datetime.datetime | None: """Deprecated method.""" @typing_extensions.deprecated("Use .acquire or .try_acquire and .release to manage cooldowns") @@ -179,9 +178,7 @@ def acquire( bucket_id: str, ctx: tanjun.Context, /, - error: collections.Callable[ - [typing.Optional[datetime.datetime]], Exception - ] = lambda cooldown: errors.CommandError( + error: collections.Callable[[datetime.datetime | None], Exception] = lambda cooldown: errors.CommandError( "This command is currently in cooldown." + (f" Try again {conversion.from_datetime(cooldown, style='R')}." if cooldown else "") ), @@ -223,7 +220,7 @@ def __init__( manager: AbstractCooldownManager, bucket_id: str, ctx: tanjun.Context, - error: collections.Callable[[typing.Optional[datetime.datetime]], Exception], + error: collections.Callable[[datetime.datetime | None], Exception], /, ) -> None: self._acquired = False @@ -245,10 +242,7 @@ async def __aenter__(self) -> None: raise self._error(exc.wait_until) from None async def __aexit__( - self, - exc_type: typing.Optional[type[BaseException]], - exc: typing.Optional[BaseException], - exc_traceback: typing.Optional[types.TracebackType], + self, exc_type: type[BaseException] | None, exc: BaseException | None, exc_traceback: types.TracebackType | None ) -> None: if not self._acquired: raise RuntimeError("Not acquired") @@ -370,10 +364,7 @@ async def __aenter__(self) -> None: raise self._error() from None # noqa: R102 async def __aexit__( - self, - exc_type: typing.Optional[type[BaseException]], - exc: typing.Optional[BaseException], - exc_traceback: typing.Optional[types.TracebackType], + self, exc_type: type[BaseException] | None, exc: BaseException | None, exc_traceback: types.TracebackType | None ) -> None: if not self._acquired: raise RuntimeError("Not acquired") @@ -423,9 +414,7 @@ class BucketResource(int, enum.Enum): """A global resource bucket.""" -async def _try_get_role( - cache: async_cache.SfCache[hikari.Role], role_id: hikari.Snowflake, / -) -> typing.Optional[hikari.Role]: +async def _try_get_role(cache: async_cache.SfCache[hikari.Role], role_id: hikari.Snowflake, /) -> hikari.Role | None: try: return await cache.get(role_id) except async_cache.EntryNotFound: @@ -440,7 +429,7 @@ async def _get_ctx_target(ctx: tanjun.Context, type_: BucketResource, /) -> hika return ctx.channel_id if type_ is BucketResource.PARENT_CHANNEL: - channel: typing.Optional[hikari.PartialChannel] # MyPy compat + channel: hikari.PartialChannel | None # MyPy compat if ctx.guild_id is None: return ctx.channel_id @@ -586,7 +575,7 @@ async def into_inner(self, ctx: tanjun.Context, /) -> _InnerResourceT: raise NotImplementedError @abc.abstractmethod - async def try_into_inner(self, ctx: tanjun.Context, /) -> typing.Optional[_InnerResourceT]: + async def try_into_inner(self, ctx: tanjun.Context, /) -> _InnerResourceT | None: raise NotImplementedError @@ -598,7 +587,7 @@ def __init__(self, resource: BucketResource, make_resource: _InnerResourceSig[_I self.mapping: dict[hikari.Snowflake, _InnerResourceT] = {} self.resource = resource - async def try_into_inner(self, ctx: tanjun.Context, /) -> typing.Optional[_InnerResourceT]: + async def try_into_inner(self, ctx: tanjun.Context, /) -> _InnerResourceT | None: return self.mapping.get(await _get_ctx_target(ctx, self.resource)) async def into_inner(self, ctx: tanjun.Context, /) -> _InnerResourceT: @@ -642,7 +631,7 @@ async def into_inner(self, ctx: tanjun.Context, /) -> _InnerResourceT: self.mapping[ctx.guild_id] = {ctx.author.id: resource} return resource - async def try_into_inner(self, ctx: tanjun.Context, /) -> typing.Optional[_InnerResourceT]: + async def try_into_inner(self, ctx: tanjun.Context, /) -> _InnerResourceT | None: if not ctx.guild_id: return self.dm_fallback.get(ctx.channel_id) @@ -672,7 +661,7 @@ def __init__(self, make_resource: _InnerResourceSig[_InnerResourceT], /) -> None super().__init__(make_resource) self.bucket = make_resource() - async def try_into_inner(self, _: tanjun.Context, /) -> typing.Optional[_InnerResourceT]: + async def try_into_inner(self, _: tanjun.Context, /) -> _InnerResourceT | None: return self.bucket async def into_inner(self, _: tanjun.Context, /) -> _InnerResourceT: @@ -770,7 +759,7 @@ def __init__(self) -> None: self._default_bucket: collections.Callable[[str], object] = lambda bucket_id: self.set_bucket( bucket_id, BucketResource.USER, 2, datetime.timedelta(seconds=5) ) - self._gc_task: typing.Optional[asyncio.Task[None]] = None + self._gc_task: asyncio.Task[None] | None = None async def _gc(self) -> None: while True: @@ -821,7 +810,7 @@ async def try_acquire(self, bucket_id: str, ctx: tanjun.Context) -> None: @typing_extensions.deprecated("Use .acquire or .try_acquire and .release to manage cooldowns") async def check_cooldown( self, bucket_id: str, ctx: tanjun.Context, /, *, increment: bool = False - ) -> typing.Optional[datetime.datetime]: + ) -> datetime.datetime | None: if increment: try: await self.try_acquire(bucket_id, ctx) @@ -873,7 +862,7 @@ def close(self) -> None: self._gc_task.cancel() self._gc_task = None - def open(self, *, _loop: typing.Optional[asyncio.AbstractEventLoop] = None) -> None: + def open(self, *, _loop: asyncio.AbstractEventLoop | None = None) -> None: """Start the cooldown manager. Raises @@ -916,12 +905,7 @@ def disable_bucket(self, bucket_id: str, /) -> Self: return self def set_bucket( - self, - bucket_id: str, - resource: BucketResource, - limit: int, - reset_after: typing.Union[int, float, datetime.timedelta], - /, + self, bucket_id: str, resource: BucketResource, limit: int, reset_after: int | float | datetime.timedelta, / ) -> Self: """Set the cooldown for a specific bucket. @@ -1035,11 +1019,11 @@ def __init__( bucket_id: str, /, *, - error: typing.Optional[collections.Callable[[str, typing.Optional[datetime.datetime]], Exception]] = None, - error_message: typing.Union[ - str, collections.Mapping[str, str] - ] = "This command is currently in cooldown. Try again {cooldown}.", - unknown_message: typing.Union[str, collections.Mapping[str, str], None] = None, + error: collections.Callable[[str, datetime.datetime | None], Exception] | None = None, + error_message: ( + str | collections.Mapping[str, str] + ) = "This command is currently in cooldown. Try again {cooldown}.", + unknown_message: str | collections.Mapping[str, str] | None = None, owners_exempt: bool = True, ) -> None: """Initialise a pre-execution cooldown command hook. @@ -1088,8 +1072,8 @@ async def __call__( /, cooldowns: alluka.Injected[AbstractCooldownManager], *, - localiser: typing.Optional[locales.AbstractLocaliser] = None, - owner_check: alluka.Injected[typing.Optional[owners.AbstractOwners]], + localiser: locales.AbstractLocaliser | None = None, + owner_check: alluka.Injected[owners.AbstractOwners | None], ) -> None: if self._owners_exempt: if not owner_check: @@ -1124,7 +1108,7 @@ class _LocaliseUnknown(localisation.MaybeLocalised): def __init__( self, field_name: str, - field: typing.Union[str, collections.Mapping[str, str], collections.Iterable[tuple[str, str]], None], + field: str | collections.Mapping[str, str] | collections.Iterable[tuple[str, str]] | None, fallback: localisation.MaybeLocalised, /, default: str, @@ -1143,7 +1127,7 @@ def __init__( def localise( self, ctx: tanjun.Context, - localiser: typing.Optional[locales.AbstractLocaliser], + localiser: locales.AbstractLocaliser | None, field_type: localisation.NamedFields, field_name: str, /, @@ -1177,11 +1161,9 @@ def with_cooldown( bucket_id: str, /, *, - error: typing.Optional[collections.Callable[[str, typing.Optional[datetime.datetime]], Exception]] = None, - error_message: typing.Union[ - str, collections.Mapping[str, str] - ] = "This command is currently in cooldown. Try again {cooldown}.", - unknown_message: typing.Union[str, collections.Mapping[str, str], None] = None, + error: collections.Callable[[str, datetime.datetime | None], Exception] | None = None, + error_message: str | collections.Mapping[str, str] = "This command is currently in cooldown. Try again {cooldown}.", + unknown_message: str | collections.Mapping[str, str] | None = None, follow_wrapped: bool = False, owners_exempt: bool = True, ) -> collections.Callable[[_CommandT], _CommandT]: @@ -1248,11 +1230,9 @@ def add_cooldown( bucket_id: str, /, *, - error: typing.Optional[collections.Callable[[str, typing.Optional[datetime.datetime]], Exception]] = None, - error_message: typing.Union[ - str, collections.Mapping[str, str] - ] = "This command is currently in cooldown. Try again {cooldown}.", - unknown_message: typing.Union[str, collections.Mapping[str, str], None] = None, + error: collections.Callable[[str, datetime.datetime | None], Exception] | None = None, + error_message: str | collections.Mapping[str, str] = "This command is currently in cooldown. Try again {cooldown}.", + unknown_message: str | collections.Mapping[str, str] | None = None, owners_exempt: bool = True, ) -> None: """Add a pre-execution hook used to manage a command's cooldown. @@ -1417,7 +1397,7 @@ def __init__(self) -> None: self._default_bucket: collections.Callable[[str], object] = lambda bucket: self.set_bucket( bucket, BucketResource.USER, 1 ) - self._gc_task: typing.Optional[asyncio.Task[None]] = None + self._gc_task: asyncio.Task[None] | None = None async def _gc(self) -> None: while True: @@ -1458,7 +1438,7 @@ def close(self) -> None: self._gc_task.cancel() self._gc_task = None - def open(self, *, _loop: typing.Optional[asyncio.AbstractEventLoop] = None) -> None: + def open(self, *, _loop: asyncio.AbstractEventLoop | None = None) -> None: """Start the concurrency manager. Raises @@ -1633,10 +1613,8 @@ def __init__( bucket_id: str, /, *, - error: typing.Optional[collections.Callable[[str], Exception]] = None, - error_message: typing.Union[ - str, collections.Mapping[str, str] - ] = "This resource is currently busy; please try again later.", + error: collections.Callable[[str], Exception] | None = None, + error_message: str | collections.Mapping[str, str] = "This resource is currently busy; please try again later.", ) -> None: """Initialise a concurrency pre-execution hook. @@ -1667,7 +1645,7 @@ async def __call__( /, limiter: alluka.Injected[AbstractConcurrencyLimiter], *, - localiser: typing.Optional[locales.AbstractLocaliser] = None, + localiser: locales.AbstractLocaliser | None = None, ) -> None: try: await limiter.try_acquire(self._bucket_id, ctx) @@ -1707,10 +1685,8 @@ def with_concurrency_limit( bucket_id: str, /, *, - error: typing.Optional[collections.Callable[[str], Exception]] = None, - error_message: typing.Union[ - str, collections.Mapping[str, str] - ] = "This resource is currently busy; please try again later.", + error: collections.Callable[[str], Exception] | None = None, + error_message: str | collections.Mapping[str, str] = "This resource is currently busy; please try again later.", follow_wrapped: bool = False, ) -> collections.Callable[[_CommandT], _CommandT]: """Add the hooks used to manage a command's concurrency limit through a decorator call. @@ -1759,10 +1735,8 @@ def add_concurrency_limit( bucket_id: str, /, *, - error: typing.Optional[collections.Callable[[str], Exception]] = None, - error_message: typing.Union[ - str, collections.Mapping[str, str] - ] = "This resource is currently busy; please try again later.", + error: collections.Callable[[str], Exception] | None = None, + error_message: str | collections.Mapping[str, str] = "This resource is currently busy; please try again later.", ) -> None: """Add the hooks used to manage a command's concurrency limit. diff --git a/tanjun/dependencies/locales.py b/tanjun/dependencies/locales.py index 5e549d21d..cb1e907f5 100644 --- a/tanjun/dependencies/locales.py +++ b/tanjun/dependencies/locales.py @@ -43,8 +43,7 @@ if typing.TYPE_CHECKING: from collections import abc as collections - - from typing_extensions import Self + from typing import Self from .. import abc as tanjun @@ -63,7 +62,7 @@ def get_all_variants(self, identifier: str, /, **kwargs: typing.Any) -> collecti """Get all the localisation variants for an identifier.""" @abc.abstractmethod - def localise(self, identifier: str, tag: str, /, **kwargs: typing.Any) -> typing.Optional[str]: + def localise(self, identifier: str, tag: str, /, **kwargs: typing.Any) -> str | None: """Localise a string with the given identifier and arguments. Parameters @@ -86,7 +85,7 @@ def localise(self, identifier: str, tag: str, /, **kwargs: typing.Any) -> typing The localised string. """ - def localize(self, identifier: str, tag: str, /, **kwargs: typing.Any) -> typing.Optional[str]: + def localize(self, identifier: str, tag: str, /, **kwargs: typing.Any) -> str | None: """Alias for `AbstractLocaliser.localise`.""" return self.localise(identifier, tag, **kwargs) @@ -120,7 +119,7 @@ def add_to_client(self, client: tanjun.Client, /) -> None: """ client.set_type_dependency(AbstractLocalizer, self) - def _get_dynamic(self, identifier: str, /) -> typing.Optional[dict[str, str]]: + def _get_dynamic(self, identifier: str, /) -> dict[str, str] | None: if self._dynamic_tags and (match := _CHECK_NAME_PATTERN.fullmatch(identifier)): command_type, _, check_name = match.groups() return self._dynamic_tags.get(f"{command_type}:*:check:{check_name}") @@ -136,7 +135,7 @@ def get_all_variants(self, identifier: str, /, **kwargs: typing.Any) -> collecti results.pop("default", None) return results - def localise(self, identifier: str, tag: str, /, **kwargs: typing.Any) -> typing.Optional[str]: + def localise(self, identifier: str, tag: str, /, **kwargs: typing.Any) -> str | None: # <>. if (tag_values := self._tags.get(identifier)) and (string := tag_values.get(tag)): return string.format(**kwargs) @@ -147,7 +146,7 @@ def localise(self, identifier: str, tag: str, /, **kwargs: typing.Any) -> typing return None # MyPy compat def set_variants( - self, identifier: str, variants: typing.Optional[collections.Mapping[str, str]] = None, /, **other_variants: str + self, identifier: str, variants: collections.Mapping[str, str] | None = None, /, **other_variants: str ) -> Self: """Set the variants for a localised field. diff --git a/tanjun/dependencies/owners.py b/tanjun/dependencies/owners.py index 726a0538d..32b9e7f55 100644 --- a/tanjun/dependencies/owners.py +++ b/tanjun/dependencies/owners.py @@ -80,11 +80,11 @@ async def check_ownership(self, client: tanjun.Client, user: hikari.User, /) -> class _CachedValue(typing.Generic[_T]): __slots__ = ("_expire_after", "_last_called", "_lock", "_result") - def __init__(self, *, expire_after: typing.Optional[float]) -> None: + def __init__(self, *, expire_after: float | None) -> None: self._expire_after = expire_after - self._last_called: typing.Optional[float] = None - self._lock: typing.Optional[asyncio.Lock] = None - self._result: typing.Optional[_T] = None + self._last_called: float | None = None + self._lock: asyncio.Lock | None = None + self._result: _T | None = None @property def _has_expired(self) -> bool: @@ -127,9 +127,9 @@ class Owners(AbstractOwners): def __init__( self, *, - expire_after: typing.Union[datetime.timedelta, int, float] = datetime.timedelta(minutes=5), + expire_after: datetime.timedelta | int | float = datetime.timedelta(minutes=5), fallback_to_application: bool = True, - owners: typing.Optional[hikari.SnowflakeishSequence[hikari.User]] = None, + owners: hikari.SnowflakeishSequence[hikari.User] | None = None, ) -> None: """Initiate a new owner check dependency. diff --git a/tanjun/dependencies/reloaders.py b/tanjun/dependencies/reloaders.py index f905182ba..147379e55 100644 --- a/tanjun/dependencies/reloaders.py +++ b/tanjun/dependencies/reloaders.py @@ -51,11 +51,10 @@ if typing.TYPE_CHECKING: from collections import abc as collections - - from typing_extensions import Self + from typing import Self _BuilderDict = dict[tuple[hikari.CommandType, str], hikari.api.CommandBuilder] - _DirectoryEntry = typing.Union[tuple[str, set[str]], tuple[None, set[pathlib.Path]]] + _DirectoryEntry = tuple[str, set[str]] | tuple[None, set[pathlib.Path]] _PathT = typing.TypeVar("_PathT", str, pathlib.Path) @@ -111,9 +110,9 @@ class HotReloader: def __init__( self, *, - commands_guild: typing.Optional[hikari.SnowflakeishOr[hikari.PartialGuild]] = None, - interval: typing.Union[int, float, datetime.timedelta] = datetime.timedelta(microseconds=500000), - redeclare_cmds_after: typing.Union[int, float, datetime.timedelta, None] = datetime.timedelta(seconds=10), + commands_guild: hikari.SnowflakeishOr[hikari.PartialGuild] | None = None, + interval: int | float | datetime.timedelta = datetime.timedelta(microseconds=500000), + redeclare_cmds_after: int | float | datetime.timedelta | None = datetime.timedelta(seconds=10), unload_on_delete: bool = True, ) -> None: r"""Initialise a hot reloader. @@ -149,10 +148,10 @@ def __init__( else: redeclare_cmds_after = float(redeclare_cmds_after) - self._command_task: typing.Optional[asyncio.Task[None]] = None + self._command_task: asyncio.Task[None] | None = None self._commands_guild: hikari.UndefinedOr[hikari.Snowflake] # MyPy was resolving this to object cause MyPy self._commands_guild = hikari.UNDEFINED if commands_guild is None else hikari.Snowflake(commands_guild) - self._dead_unloads: set[typing.Union[str, pathlib.Path]] = set() + self._dead_unloads: set[str | pathlib.Path] = set() """Set of modules which cannot be unloaded.""" self._declared_builders: _BuilderDict = {} """State of the last declared builders.""" @@ -171,7 +170,7 @@ def __init__( self._sys_paths: dict[pathlib.Path, _PyPathInfo] = {} """Dict of system paths to info of files being targeted.""" - self._task: typing.Optional[asyncio.Task[None]] = None + self._task: asyncio.Task[None] | None = None self._unload_on_delete = unload_on_delete self._waiting_for_py: dict[str, int] = {} @@ -199,7 +198,7 @@ def add_to_client(self, client: tanjun.Client, /) -> None: if client.is_alive and client.loop: client.loop.call_soon_threadsafe(self.start, client) - async def add_modules_async(self, *paths: typing.Union[str, pathlib.Path]) -> Self: + async def add_modules_async(self, *paths: str | pathlib.Path) -> Self: """Asynchronous variant of [HotReloader.add_modules][tanjun.dependencies.reloaders.HotReloader.add_modules]. Unlike [HotReloader.add_modules][tanjun.dependencies.reloaders.HotReloader.add_modules], @@ -213,7 +212,7 @@ async def add_modules_async(self, *paths: typing.Union[str, pathlib.Path]) -> Se self._sys_paths.update((key, _PyPathInfo(key)) for key in sys_paths) return self - def add_modules(self, *paths: typing.Union[str, pathlib.Path]) -> Self: + def add_modules(self, *paths: str | pathlib.Path) -> Self: """Add modules for this hot reloader to track. Parameters @@ -236,9 +235,7 @@ def add_modules(self, *paths: typing.Union[str, pathlib.Path]) -> Self: self._sys_paths.update((key, _PyPathInfo(key)) for key in sys_paths) return self - async def add_directory_async( - self, directory: typing.Union[str, pathlib.Path], /, *, namespace: typing.Optional[str] = None - ) -> Self: + async def add_directory_async(self, directory: str | pathlib.Path, /, *, namespace: str | None = None) -> Self: """Asynchronous variant of [HotReloader.add_directory][tanjun.dependencies.reloaders.HotReloader.add_directory]. Unlike [HotReloader.add_directory][tanjun.dependencies.reloaders.HotReloader.add_directory], @@ -251,9 +248,7 @@ async def add_directory_async( self._directories[path] = info return self - def add_directory( - self, directory: typing.Union[str, pathlib.Path], /, *, namespace: typing.Optional[str] = None - ) -> Self: + def add_directory(self, directory: str | pathlib.Path, /, *, namespace: str | None = None) -> Self: """Add a directory for this hot reloader to track. !!! note @@ -291,7 +286,7 @@ def add_directory( self._directories[path] = info return self - async def _load_module(self, client: tanjun.Client, path: typing.Union[str, pathlib.Path], /) -> bool: + async def _load_module(self, client: tanjun.Client, path: str | pathlib.Path, /) -> bool: for method in (client.reload_modules_async, client.load_modules_async): try: await method(path) @@ -328,7 +323,7 @@ async def _load_module(self, client: tanjun.Client, path: typing.Union[str, path return False - def _unload_module(self, client: tanjun.Client, path: typing.Union[str, pathlib.Path], /) -> bool: + def _unload_module(self, client: tanjun.Client, path: str | pathlib.Path, /) -> bool: try: client.unload_modules(path) @@ -503,9 +498,7 @@ def _to_namespace(namespace: str, path: pathlib.Path, /) -> str: return namespace + "." + path.name.removesuffix(".py") -def _add_directory( - directory: typing.Union[str, pathlib.Path], namespace: typing.Optional[str], / -) -> tuple[pathlib.Path, _DirectoryEntry]: +def _add_directory(directory: str | pathlib.Path, namespace: str | None, /) -> tuple[pathlib.Path, _DirectoryEntry]: directory = pathlib.Path(directory) if not directory.exists(): raise FileNotFoundError(f"{directory} does not exist") @@ -513,9 +506,7 @@ def _add_directory( return directory.resolve(), (namespace, set()) if namespace is None else (namespace, set()) -def _add_modules( - paths: tuple[typing.Union[str, pathlib.Path], ...], / -) -> tuple[dict[str, _PyPathInfo], list[pathlib.Path]]: +def _add_modules(paths: tuple[str | pathlib.Path, ...], /) -> tuple[dict[str, _PyPathInfo], list[pathlib.Path]]: py_paths: dict[str, _PyPathInfo] = {} sys_paths: list[pathlib.Path] = [] @@ -540,7 +531,7 @@ def _add_modules( return py_paths, sys_paths -def _scan_one(path: pathlib.Path, /) -> typing.Optional[int]: +def _scan_one(path: pathlib.Path, /) -> int | None: try: return path.stat().st_mtime_ns @@ -561,7 +552,7 @@ class _PathScanner(typing.Generic[_PathT]): __slots__ = ("dead_unloads", "global_paths", "removed_paths", "result_paths") global_paths: dict[_PathT, _PyPathInfo] - dead_unloads: set[typing.Union[str, pathlib.Path]] + dead_unloads: set[str | pathlib.Path] result_paths: dict[_PathT, _PyPathInfo] removed_paths: list[_PathT] @@ -600,9 +591,9 @@ class _PathLoader(typing.Generic[_PathT]): waiting_for: dict[_PathT, int] paths: dict[_PathT, _PyPathInfo] load_module: collections.Callable[ - [tanjun.Client, typing.Union[str, pathlib.Path]], collections.Coroutine[typing.Any, typing.Any, bool] + [tanjun.Client, str | pathlib.Path], collections.Coroutine[typing.Any, typing.Any, bool] ] - unload_module: collections.Callable[[tanjun.Client, typing.Union[str, pathlib.Path]], bool] + unload_module: collections.Callable[[tanjun.Client, str | pathlib.Path], bool] changed: bool = dataclasses.field(default=False, init=False) async def process_results( diff --git a/tanjun/errors.py b/tanjun/errors.py index d6f02a800..d768bbc32 100644 --- a/tanjun/errors.py +++ b/tanjun/errors.py @@ -84,7 +84,7 @@ class CommandError(TanjunError): content: hikari.UndefinedOr[str] """The response error message's content.""" - delete_after: typing.Union[datetime.timedelta, float, int, None] + delete_after: datetime.timedelta | float | int | None """The seconds after which the response message should be deleted, if set.""" attachments: hikari.UndefinedOr[collections.Sequence[hikari.Resourceish]] @@ -99,7 +99,7 @@ class CommandError(TanjunError): mentions_everyone: hikari.UndefinedOr[bool] """Whether or not the response should be allowed to mention `@everyone`/`@here`.""" - user_mentions: typing.Union[hikari.SnowflakeishSequence[hikari.PartialUser], bool, hikari.UndefinedType] + user_mentions: hikari.SnowflakeishSequence[hikari.PartialUser] | bool | hikari.UndefinedType """Configuration for the response's allowed user mentions. If this is a sequence then the response will only be allowed to mention @@ -109,7 +109,7 @@ class CommandError(TanjunError): if the value is `True`. """ - role_mentions: typing.Union[hikari.SnowflakeishSequence[hikari.PartialRole], bool, hikari.UndefinedType] + role_mentions: hikari.SnowflakeishSequence[hikari.PartialRole] | bool | hikari.UndefinedType """Configuration for the response's allowed role mentions. If this is a sequence then the response will only be allowed to mention @@ -123,7 +123,7 @@ def __init__( self, content: hikari.UndefinedOr[typing.Any] = hikari.UNDEFINED, *, - delete_after: typing.Union[datetime.timedelta, float, int, None] = None, + delete_after: datetime.timedelta | float | int | None = None, attachment: hikari.UndefinedOr[hikari.Resourceish] = hikari.UNDEFINED, attachments: hikari.UndefinedOr[collections.Sequence[hikari.Resourceish]] = hikari.UNDEFINED, component: hikari.UndefinedOr[hikari.api.ComponentBuilder] = hikari.UNDEFINED, @@ -131,12 +131,8 @@ def __init__( embed: hikari.UndefinedOr[hikari.Embed] = hikari.UNDEFINED, embeds: hikari.UndefinedOr[collections.Sequence[hikari.Embed]] = hikari.UNDEFINED, mentions_everyone: hikari.UndefinedOr[bool] = hikari.UNDEFINED, - user_mentions: typing.Union[ - hikari.SnowflakeishSequence[hikari.PartialUser], bool, hikari.UndefinedType - ] = hikari.UNDEFINED, - role_mentions: typing.Union[ - hikari.SnowflakeishSequence[hikari.PartialRole], bool, hikari.UndefinedType - ] = hikari.UNDEFINED, + user_mentions: hikari.SnowflakeishSequence[hikari.PartialUser] | bool | hikari.UndefinedType = hikari.UNDEFINED, + role_mentions: hikari.SnowflakeishSequence[hikari.PartialRole] | bool | hikari.UndefinedType = hikari.UNDEFINED, ) -> None: """Initialise a command error. @@ -232,9 +228,9 @@ def __str__(self) -> str: async def send(self, ctx: tanjun.Context, /, *, ensure_result: typing.Literal[True]) -> hikari.Message: ... @typing.overload - async def send(self, ctx: tanjun.Context, /, *, ensure_result: bool = False) -> typing.Optional[hikari.Message]: ... + async def send(self, ctx: tanjun.Context, /, *, ensure_result: bool = False) -> hikari.Message | None: ... - async def send(self, ctx: tanjun.Context, /, *, ensure_result: bool = False) -> typing.Optional[hikari.Message]: + async def send(self, ctx: tanjun.Context, /, *, ensure_result: bool = False) -> hikari.Message | None: """Send this error as a command response. Parameters @@ -311,7 +307,7 @@ class ParserError(TanjunError, ValueError): This may be used as a command response message. """ - parameter: typing.Optional[str] + parameter: str | None """Name of the this was raised for. !!! note @@ -319,7 +315,7 @@ class ParserError(TanjunError, ValueError): provided message content. """ - def __init__(self, message: str, parameter: typing.Optional[str], /) -> None: + def __init__(self, message: str, parameter: str | None, /) -> None: """Initialise a parser error. Parameters @@ -401,7 +397,7 @@ def __init__(self, message: str, parameter: str, /) -> None: class ModuleMissingLoaders(RuntimeError, TanjunError): """Error raised when a module is missing loaders.""" - def __init__(self, message: str, path: typing.Union[str, pathlib.Path], /) -> None: + def __init__(self, message: str, path: str | pathlib.Path, /) -> None: self._message = message self._path = path @@ -411,7 +407,7 @@ def message(self) -> str: return self._message @property - def path(self) -> typing.Union[str, pathlib.Path]: + def path(self) -> str | pathlib.Path: """The path of the module which is missing loaders.""" return self._path @@ -419,7 +415,7 @@ def path(self) -> typing.Union[str, pathlib.Path]: class ModuleMissingUnloaders(RuntimeError, TanjunError): """Error raised when a module is missing unloaders.""" - def __init__(self, message: str, path: typing.Union[str, pathlib.Path], /) -> None: + def __init__(self, message: str, path: str | pathlib.Path, /) -> None: self._message = message self._path = path @@ -429,7 +425,7 @@ def message(self) -> str: return self._message @property - def path(self) -> typing.Union[str, pathlib.Path]: + def path(self) -> str | pathlib.Path: """The path of the module which is missing unloaders.""" return self._path @@ -437,7 +433,7 @@ def path(self) -> typing.Union[str, pathlib.Path]: class ModuleStateConflict(ValueError, TanjunError): """Error raised when a module cannot be (un)loaded due to a state conflict.""" - def __init__(self, message: str, path: typing.Union[str, pathlib.Path], /) -> None: + def __init__(self, message: str, path: str | pathlib.Path, /) -> None: self._message = message self._path = path @@ -447,7 +443,7 @@ def message(self) -> str: return self._message @property - def path(self) -> typing.Union[str, pathlib.Path]: + def path(self) -> str | pathlib.Path: """The path of the module which caused the error.""" return self._path @@ -465,11 +461,11 @@ class FailedModuleLoad(TanjunError): __cause__: Exception """The root error.""" - def __init__(self, path: typing.Union[str, pathlib.Path], /) -> None: + def __init__(self, path: str | pathlib.Path, /) -> None: self._path = path @property - def path(self) -> typing.Union[str, pathlib.Path]: + def path(self) -> str | pathlib.Path: """The path of the module which caused the error.""" return self._path @@ -494,10 +490,10 @@ class FailedModuleUnload(TanjunError): __cause__: Exception """The root error.""" - def __init__(self, path: typing.Union[str, pathlib.Path], /) -> None: + def __init__(self, path: str | pathlib.Path, /) -> None: self._path = path @property - def path(self) -> typing.Union[str, pathlib.Path]: + def path(self) -> str | pathlib.Path: """The path of the module which caused the error.""" return self._path diff --git a/tanjun/hooks.py b/tanjun/hooks.py index 24f4802b3..aa0d7ec12 100644 --- a/tanjun/hooks.py +++ b/tanjun/hooks.py @@ -42,8 +42,7 @@ if typing.TYPE_CHECKING: from collections import abc as collections - - from typing_extensions import Self + from typing import Self _AnyCommandT = typing.TypeVar("_AnyCommandT", bound=tanjun.ExecutableCommand[typing.Any]) _CommandT = typing.TypeVar("_CommandT", bound=tanjun.ExecutableCommand[tanjun.Context]) @@ -149,7 +148,7 @@ def add_on_error(self, callback: tanjun.ErrorHookSig[_ContextT_contra], /) -> Se self._error_callbacks.append(callback) return self - def set_on_error(self, callback: typing.Optional[tanjun.ErrorHookSig[_ContextT_contra]], /) -> Self: + def set_on_error(self, callback: tanjun.ErrorHookSig[_ContextT_contra] | None, /) -> Self: """Set the error callback for this hook object. !!! note @@ -202,7 +201,7 @@ def add_on_parser_error(self, callback: tanjun.ParserHookSig[_ContextT_contra], self._parser_error_callbacks.append(callback) return self - def set_on_parser_error(self, callback: typing.Optional[tanjun.ParserHookSig[_ContextT_contra]], /) -> Self: + def set_on_parser_error(self, callback: tanjun.ParserHookSig[_ContextT_contra] | None, /) -> Self: """Set the parser error callback for this hook object. Parameters @@ -248,7 +247,7 @@ def add_post_execution(self, callback: tanjun.HookSig[_ContextT_contra], /) -> S self._post_execution_callbacks.append(callback) return self - def set_post_execution(self, callback: typing.Optional[tanjun.HookSig[_ContextT_contra]], /) -> Self: + def set_post_execution(self, callback: tanjun.HookSig[_ContextT_contra] | None, /) -> Self: """Set the post-execution callback for this hook object. Parameters @@ -291,7 +290,7 @@ def add_pre_execution(self, callback: tanjun.HookSig[_ContextT_contra], /) -> Se self._pre_execution_callbacks.append(callback) return self - def set_pre_execution(self, callback: typing.Optional[tanjun.HookSig[_ContextT_contra]], /) -> Self: + def set_pre_execution(self, callback: tanjun.HookSig[_ContextT_contra] | None, /) -> Self: """Set the pre-execution callback for this hook object. Parameters @@ -334,7 +333,7 @@ def add_on_success(self, callback: tanjun.HookSig[_ContextT_contra], /) -> Self: self._success_callbacks.append(callback) return self - def set_on_success(self, callback: typing.Optional[tanjun.HookSig[_ContextT_contra]], /) -> Self: + def set_on_success(self, callback: tanjun.HookSig[_ContextT_contra] | None, /) -> Self: """Set the success callback for this hook object. Parameters @@ -378,7 +377,7 @@ async def trigger_error( exception: Exception, /, *, - hooks: typing.Optional[collections.Set[tanjun.Hooks[_ContextT_contra]]] = None, + hooks: collections.Set[tanjun.Hooks[_ContextT_contra]] | None = None, ) -> int: # <>. level = 0 @@ -397,11 +396,7 @@ async def trigger_error( return level async def trigger_post_execution( - self, - ctx: _ContextT_contra, - /, - *, - hooks: typing.Optional[collections.Set[tanjun.Hooks[_ContextT_contra]]] = None, + self, ctx: _ContextT_contra, /, *, hooks: collections.Set[tanjun.Hooks[_ContextT_contra]] | None = None ) -> None: # <>. if self._post_execution_callbacks: @@ -411,11 +406,7 @@ async def trigger_post_execution( await asyncio.gather(*(hook.trigger_post_execution(ctx) for hook in hooks)) async def trigger_pre_execution( - self, - ctx: _ContextT_contra, - /, - *, - hooks: typing.Optional[collections.Set[tanjun.Hooks[_ContextT_contra]]] = None, + self, ctx: _ContextT_contra, /, *, hooks: collections.Set[tanjun.Hooks[_ContextT_contra]] | None = None ) -> None: # <>. if self._pre_execution_callbacks: @@ -425,11 +416,7 @@ async def trigger_pre_execution( await asyncio.gather(*(hook.trigger_pre_execution(ctx) for hook in hooks)) async def trigger_success( - self, - ctx: _ContextT_contra, - /, - *, - hooks: typing.Optional[collections.Set[tanjun.Hooks[_ContextT_contra]]] = None, + self, ctx: _ContextT_contra, /, *, hooks: collections.Set[tanjun.Hooks[_ContextT_contra]] | None = None ) -> None: # <>. if self._success_callbacks: diff --git a/tanjun/parsing.py b/tanjun/parsing.py index c93afa94b..c09841070 100644 --- a/tanjun/parsing.py +++ b/tanjun/parsing.py @@ -61,7 +61,7 @@ from . import errors if typing.TYPE_CHECKING: - from typing_extensions import Self + from typing import Self _CommandT = typing.TypeVar("_CommandT", bound=tanjun.MessageCommand[typing.Any]) _T_contra = typing.TypeVar("_T_contra", contravariant=True) @@ -78,30 +78,21 @@ def __len__(self) -> int: raise NotImplementedError _CmpProtoT = typing.TypeVar("_CmpProtoT", bound=_CmpProto[typing.Any]) + # Pyright bug doesn't accept Var = Class | Class as a type _MaybeIterable = typing.Union[collections.Iterable["_T"], "_T"] _SizedCmpProtoT = typing.TypeVar("_SizedCmpProtoT", bound=_SizedCmpProto[typing.Any]) _T = typing.TypeVar("_T") -# 3.9 and 3.10 just can't handle ending Concatenate with ... so we lie about this at runtime. -if typing.TYPE_CHECKING: - ConverterSig = collections.Callable[ - typing_extensions.Concatenate[str, ...], typing.Union[collections.Coroutine[typing.Any, typing.Any, _T], _T] - ] - """Type hint of a converter used within a parser instance. - - This represents the signatures `def (str, ...) -> Any` and - `async def (str, ...) -> Any` where dependency injection is supported. - """ - -else: - import types - - ConverterSig = types.GenericAlias( - collections.Callable[..., typing.Union[collections.Coroutine[typing.Any, typing.Any, _T], _T]], (_T,) - ) +ConverterSig = collections.Callable[ + typing.Concatenate[str, ...], collections.Coroutine[typing.Any, typing.Any, _T] | _T +] +"""Type hint of a converter used within a parser instance. +This represents the signatures `def (str, ...) -> Any` and +`async def (str, ...) -> Any` where dependency injection is supported. +""" UndefinedT = tanjun.NoDefault """Deprecated alias of `typing.Literal[tanjun.abc.NO_DEFAULT]`.""" @@ -154,10 +145,10 @@ def add_argument( *, default: typing.Any = tanjun.NO_DEFAULT, greedy: bool = False, - min_length: typing.Optional[int] = None, - max_length: typing.Optional[int] = None, - min_value: typing.Optional[_CmpProto[str]] = None, - max_value: typing.Optional[_CmpProto[str]] = None, + min_length: int | None = None, + max_length: int | None = None, + min_value: _CmpProto[str] | None = None, + max_value: _CmpProto[str] | None = None, multi: bool = False, ) -> Self: ... @@ -171,10 +162,10 @@ def add_argument( *, default: typing.Any = tanjun.NO_DEFAULT, greedy: bool = False, - min_length: typing.Optional[int] = None, - max_length: typing.Optional[int] = None, - min_value: typing.Optional[_SizedCmpProtoT] = None, - max_value: typing.Optional[_SizedCmpProtoT] = None, + min_length: int | None = None, + max_length: int | None = None, + min_value: _SizedCmpProtoT | None = None, + max_value: _SizedCmpProtoT | None = None, multi: bool = False, ) -> Self: ... @@ -188,8 +179,8 @@ def add_argument( *, default: typing.Any = tanjun.NO_DEFAULT, greedy: bool = False, - min_length: typing.Optional[int] = None, - max_length: typing.Optional[int] = None, + min_length: int | None = None, + max_length: int | None = None, multi: bool = False, ) -> Self: ... @@ -203,8 +194,8 @@ def add_argument( *, default: typing.Any = tanjun.NO_DEFAULT, greedy: bool = False, - min_value: typing.Optional[_CmpProtoT] = None, - max_value: typing.Optional[_CmpProtoT] = None, + min_value: _CmpProtoT | None = None, + max_value: _CmpProtoT | None = None, multi: bool = False, ) -> Self: ... @@ -217,10 +208,10 @@ def add_argument( *, default: typing.Any = tanjun.NO_DEFAULT, greedy: bool = False, - min_length: typing.Optional[int] = None, - max_length: typing.Optional[int] = None, - min_value: typing.Optional[typing.Any] = None, - max_value: typing.Optional[typing.Any] = None, + min_length: int | None = None, + max_length: int | None = None, + min_value: typing.Any | None = None, + max_value: typing.Any | None = None, multi: bool = False, ) -> Self: """Add a positional argument type to the parser.. @@ -309,10 +300,10 @@ def add_option( converters: _MaybeIterable[ConverterSig[str]] = (), default: typing.Any, empty_value: typing.Any = tanjun.NO_DEFAULT, - min_length: typing.Optional[int] = None, - max_length: typing.Optional[int] = None, - min_value: typing.Optional[_CmpProto[str]] = None, - max_value: typing.Optional[_CmpProto[str]] = None, + min_length: int | None = None, + max_length: int | None = None, + min_value: _CmpProto[str] | None = None, + max_value: _CmpProto[str] | None = None, multi: bool = False, ) -> Self: ... @@ -327,10 +318,10 @@ def add_option( converters: _MaybeIterable[ConverterSig[_SizedCmpProtoT]], default: typing.Any, empty_value: typing.Any = tanjun.NO_DEFAULT, - min_length: typing.Optional[int] = None, - max_length: typing.Optional[int] = None, - min_value: typing.Optional[_SizedCmpProtoT] = None, - max_value: typing.Optional[_SizedCmpProtoT] = None, + min_length: int | None = None, + max_length: int | None = None, + min_value: _SizedCmpProtoT | None = None, + max_value: _SizedCmpProtoT | None = None, multi: bool = False, ) -> Self: ... @@ -345,8 +336,8 @@ def add_option( converters: _MaybeIterable[ConverterSig[collections.Sized]], default: typing.Any, empty_value: typing.Any = tanjun.NO_DEFAULT, - min_length: typing.Optional[int] = None, - max_length: typing.Optional[int] = None, + min_length: int | None = None, + max_length: int | None = None, multi: bool = False, ) -> Self: ... @@ -361,8 +352,8 @@ def add_option( converters: _MaybeIterable[ConverterSig[_CmpProtoT]], default: typing.Any, empty_value: typing.Any = tanjun.NO_DEFAULT, - min_value: typing.Optional[_CmpProtoT] = None, - max_value: typing.Optional[_CmpProtoT] = None, + min_value: _CmpProtoT | None = None, + max_value: _CmpProtoT | None = None, multi: bool = False, ) -> Self: ... @@ -376,10 +367,10 @@ def add_option( converters: _MaybeIterable[ConverterSig[typing.Any]] = (), default: typing.Any, empty_value: typing.Any = tanjun.NO_DEFAULT, - min_length: typing.Optional[int] = None, - max_length: typing.Optional[int] = None, - min_value: typing.Optional[typing.Any] = None, - max_value: typing.Optional[typing.Any] = None, + min_length: int | None = None, + max_length: int | None = None, + min_value: typing.Any | None = None, + max_value: typing.Any | None = None, multi: bool = False, ) -> Self: """Add an named option to this parser. @@ -459,16 +450,16 @@ class _ShlexTokenizer: def __init__(self, content: str, /) -> None: self.__arg_buffer: list[str] = [] - self.__last_name: typing.Optional[str] = None - self.__options_buffer: list[tuple[str, typing.Optional[str]]] = [] + self.__last_name: str | None = None + self.__options_buffer: list[tuple[str, str | None]] = [] self.__shlex = shlex.shlex(content, posix=True) self.__shlex.commenters = "" self.__shlex.quotes = '"' self.__shlex.whitespace = " " self.__shlex.whitespace_split = True - def collect_raw_options(self) -> collections.Mapping[str, collections.Sequence[typing.Optional[str]]]: - results: dict[str, list[typing.Optional[str]]] = {} + def collect_raw_options(self) -> collections.Mapping[str, collections.Sequence[str | None]]: + results: dict[str, list[str | None]] = {} while (option := self.next_raw_option()) is not None: name, value = option @@ -484,7 +475,7 @@ def iter_raw_arguments(self) -> collections.Iterator[str]: while (argument := self.next_raw_argument()) is not None: yield argument - def next_raw_argument(self) -> typing.Optional[str]: + def next_raw_argument(self) -> str | None: if self.__arg_buffer: return self.__arg_buffer.pop(0) @@ -493,7 +484,7 @@ def next_raw_argument(self) -> typing.Optional[str]: return value[1] if value else None - def next_raw_option(self) -> typing.Optional[tuple[str, typing.Optional[str]]]: + def next_raw_option(self) -> tuple[str, str | None] | None: if self.__options_buffer: return self.__options_buffer.pop(0) @@ -502,9 +493,7 @@ def next_raw_option(self) -> typing.Optional[tuple[str, typing.Optional[str]]]: return value[1] if value else None - def __seek_shlex( - self, - ) -> typing.Union[tuple[typing.Literal[0], str], tuple[typing.Literal[1], tuple[str, typing.Optional[str]]], None]: + def __seek_shlex(self) -> tuple[typing.Literal[0], str] | tuple[typing.Literal[1], tuple[str, str | None]] | None: option_name = self.__last_name try: @@ -537,7 +526,7 @@ def __seek_shlex( async def _covert_option_or_empty( - ctx: tanjun.MessageContext, option: Option, value: typing.Optional[typing.Any], / + ctx: tanjun.MessageContext, option: Option, value: typing.Any | None, / ) -> typing.Any: if value is not None: return await option.convert(ctx, value) @@ -649,10 +638,10 @@ def with_argument( *, default: typing.Any = tanjun.NO_DEFAULT, greedy: bool = False, - min_length: typing.Optional[int] = None, - max_length: typing.Optional[int] = None, - min_value: typing.Optional[_CmpProto[str]] = None, - max_value: typing.Optional[_CmpProto[str]] = None, + min_length: int | None = None, + max_length: int | None = None, + min_value: _CmpProto[str] | None = None, + max_value: _CmpProto[str] | None = None, multi: bool = False, ) -> collections.Callable[[_CommandT], _CommandT]: ... @@ -665,10 +654,10 @@ def with_argument( *, default: typing.Any = tanjun.NO_DEFAULT, greedy: bool = False, - min_length: typing.Optional[int] = None, - max_length: typing.Optional[int] = None, - min_value: typing.Optional[_SizedCmpProtoT] = None, - max_value: typing.Optional[_SizedCmpProtoT] = None, + min_length: int | None = None, + max_length: int | None = None, + min_value: _SizedCmpProtoT | None = None, + max_value: _SizedCmpProtoT | None = None, multi: bool = False, ) -> collections.Callable[[_CommandT], _CommandT]: ... @@ -681,8 +670,8 @@ def with_argument( *, default: typing.Any = tanjun.NO_DEFAULT, greedy: bool = False, - min_length: typing.Optional[int] = None, - max_length: typing.Optional[int] = None, + min_length: int | None = None, + max_length: int | None = None, multi: bool = False, ) -> collections.Callable[[_CommandT], _CommandT]: ... @@ -695,8 +684,8 @@ def with_argument( *, default: typing.Any = tanjun.NO_DEFAULT, greedy: bool = False, - min_value: typing.Optional[_CmpProtoT] = None, - max_value: typing.Optional[_CmpProtoT] = None, + min_value: _CmpProtoT | None = None, + max_value: _CmpProtoT | None = None, multi: bool = False, ) -> collections.Callable[[_CommandT], _CommandT]: ... @@ -708,10 +697,10 @@ def with_argument( *, default: typing.Any = tanjun.NO_DEFAULT, greedy: bool = False, - min_length: typing.Optional[int] = None, - max_length: typing.Optional[int] = None, - min_value: typing.Optional[typing.Any] = None, - max_value: typing.Optional[typing.Any] = None, + min_length: int | None = None, + max_length: int | None = None, + min_value: typing.Any | None = None, + max_value: typing.Any | None = None, multi: bool = False, ) -> collections.Callable[[_CommandT], _CommandT]: """Add an argument to a message command through a decorator call. @@ -826,10 +815,10 @@ def with_greedy_argument( converters: _MaybeIterable[ConverterSig[str]] = (), *, default: typing.Any = tanjun.NO_DEFAULT, - min_length: typing.Optional[int] = None, - max_length: typing.Optional[int] = None, - min_value: typing.Optional[_CmpProto[str]] = None, - max_value: typing.Optional[_CmpProto[str]] = None, + min_length: int | None = None, + max_length: int | None = None, + min_value: _CmpProto[str] | None = None, + max_value: _CmpProto[str] | None = None, ) -> collections.Callable[[_CommandT], _CommandT]: ... @@ -840,10 +829,10 @@ def with_greedy_argument( converters: _MaybeIterable[ConverterSig[_SizedCmpProtoT]], *, default: typing.Any = tanjun.NO_DEFAULT, - min_length: typing.Optional[int] = None, - max_length: typing.Optional[int] = None, - min_value: typing.Optional[_SizedCmpProtoT] = None, - max_value: typing.Optional[_SizedCmpProtoT] = None, + min_length: int | None = None, + max_length: int | None = None, + min_value: _SizedCmpProtoT | None = None, + max_value: _SizedCmpProtoT | None = None, ) -> collections.Callable[[_CommandT], _CommandT]: ... @@ -854,8 +843,8 @@ def with_greedy_argument( converters: _MaybeIterable[ConverterSig[collections.Sized]], *, default: typing.Any = tanjun.NO_DEFAULT, - min_length: typing.Optional[int] = None, - max_length: typing.Optional[int] = None, + min_length: int | None = None, + max_length: int | None = None, ) -> collections.Callable[[_CommandT], _CommandT]: ... @@ -866,8 +855,8 @@ def with_greedy_argument( converters: _MaybeIterable[ConverterSig[_CmpProtoT]], *, default: typing.Any = tanjun.NO_DEFAULT, - min_value: typing.Optional[_CmpProtoT] = None, - max_value: typing.Optional[_CmpProtoT] = None, + min_value: _CmpProtoT | None = None, + max_value: _CmpProtoT | None = None, ) -> collections.Callable[[_CommandT], _CommandT]: ... @@ -877,10 +866,10 @@ def with_greedy_argument( converters: _MaybeIterable[ConverterSig[typing.Any]] = (), *, default: typing.Any = tanjun.NO_DEFAULT, - min_length: typing.Optional[int] = None, - max_length: typing.Optional[int] = None, - min_value: typing.Optional[typing.Any] = None, - max_value: typing.Optional[typing.Any] = None, + min_length: int | None = None, + max_length: int | None = None, + min_value: typing.Any | None = None, + max_value: typing.Any | None = None, ) -> collections.Callable[[_CommandT], _CommandT]: """Add a greedy argument to a message command through a decorator call. @@ -990,10 +979,10 @@ def with_multi_argument( converters: _MaybeIterable[ConverterSig[str]] = (), *, default: typing.Any = tanjun.NO_DEFAULT, - min_length: typing.Optional[int] = None, - max_length: typing.Optional[int] = None, - min_value: typing.Optional[_CmpProto[str]] = None, - max_value: typing.Optional[_CmpProto[str]] = None, + min_length: int | None = None, + max_length: int | None = None, + min_value: _CmpProto[str] | None = None, + max_value: _CmpProto[str] | None = None, ) -> collections.Callable[[_CommandT], _CommandT]: ... @@ -1004,10 +993,10 @@ def with_multi_argument( converters: _MaybeIterable[ConverterSig[_SizedCmpProtoT]], *, default: typing.Any = tanjun.NO_DEFAULT, - min_length: typing.Optional[int] = None, - max_length: typing.Optional[int] = None, - min_value: typing.Optional[_SizedCmpProtoT] = None, - max_value: typing.Optional[_SizedCmpProtoT] = None, + min_length: int | None = None, + max_length: int | None = None, + min_value: _SizedCmpProtoT | None = None, + max_value: _SizedCmpProtoT | None = None, ) -> collections.Callable[[_CommandT], _CommandT]: ... @@ -1018,8 +1007,8 @@ def with_multi_argument( converters: _MaybeIterable[ConverterSig[collections.Sized]], *, default: typing.Any = tanjun.NO_DEFAULT, - min_length: typing.Optional[int] = None, - max_length: typing.Optional[int] = None, + min_length: int | None = None, + max_length: int | None = None, ) -> collections.Callable[[_CommandT], _CommandT]: ... @@ -1030,8 +1019,8 @@ def with_multi_argument( converters: _MaybeIterable[ConverterSig[_CmpProtoT]], *, default: typing.Any = tanjun.NO_DEFAULT, - min_value: typing.Optional[_CmpProtoT] = None, - max_value: typing.Optional[_CmpProtoT] = None, + min_value: _CmpProtoT | None = None, + max_value: _CmpProtoT | None = None, ) -> collections.Callable[[_CommandT], _CommandT]: ... @@ -1041,10 +1030,10 @@ def with_multi_argument( converters: _MaybeIterable[ConverterSig[typing.Any]] = (), *, default: typing.Any = tanjun.NO_DEFAULT, - min_length: typing.Optional[int] = None, - max_length: typing.Optional[int] = None, - min_value: typing.Optional[typing.Any] = None, - max_value: typing.Optional[typing.Any] = None, + min_length: int | None = None, + max_length: int | None = None, + min_value: typing.Any | None = None, + max_value: typing.Any | None = None, ) -> collections.Callable[[_CommandT], _CommandT]: """Add a multi-argument to a message command through a decorator call. @@ -1161,10 +1150,10 @@ def with_option( converters: _MaybeIterable[ConverterSig[str]] = (), default: typing.Any, empty_value: typing.Any = tanjun.NO_DEFAULT, - min_length: typing.Optional[int] = None, - max_length: typing.Optional[int] = None, - min_value: typing.Optional[_CmpProto[str]] = None, - max_value: typing.Optional[_CmpProto[str]] = None, + min_length: int | None = None, + max_length: int | None = None, + min_value: _CmpProto[str] | None = None, + max_value: _CmpProto[str] | None = None, multi: bool = False, ) -> collections.Callable[[_CommandT], _CommandT]: ... @@ -1178,10 +1167,10 @@ def with_option( converters: _MaybeIterable[ConverterSig[_SizedCmpProtoT]], default: typing.Any, empty_value: typing.Any = tanjun.NO_DEFAULT, - min_length: typing.Optional[int] = None, - max_length: typing.Optional[int] = None, - min_value: typing.Optional[_SizedCmpProtoT] = None, - max_value: typing.Optional[_SizedCmpProtoT] = None, + min_length: int | None = None, + max_length: int | None = None, + min_value: _SizedCmpProtoT | None = None, + max_value: _SizedCmpProtoT | None = None, multi: bool = False, ) -> collections.Callable[[_CommandT], _CommandT]: ... @@ -1195,8 +1184,8 @@ def with_option( converters: _MaybeIterable[ConverterSig[collections.Sized]], default: typing.Any, empty_value: typing.Any = tanjun.NO_DEFAULT, - min_length: typing.Optional[int] = None, - max_length: typing.Optional[int] = None, + min_length: int | None = None, + max_length: int | None = None, multi: bool = False, ) -> collections.Callable[[_CommandT], _CommandT]: ... @@ -1210,8 +1199,8 @@ def with_option( converters: _MaybeIterable[ConverterSig[_CmpProtoT]], default: typing.Any, empty_value: typing.Any = tanjun.NO_DEFAULT, - min_value: typing.Optional[_CmpProtoT] = None, - max_value: typing.Optional[_CmpProtoT] = None, + min_value: _CmpProtoT | None = None, + max_value: _CmpProtoT | None = None, multi: bool = False, ) -> collections.Callable[[_CommandT], _CommandT]: ... @@ -1225,10 +1214,10 @@ def with_option( converters: _MaybeIterable[ConverterSig[typing.Any]] = (), default: typing.Any, empty_value: typing.Any = tanjun.NO_DEFAULT, - min_length: typing.Optional[int] = None, - max_length: typing.Optional[int] = None, - min_value: typing.Optional[typing.Any] = None, - max_value: typing.Optional[typing.Any] = None, + min_length: int | None = None, + max_length: int | None = None, + min_value: typing.Any | None = None, + max_value: typing.Any | None = None, multi: bool = False, ) -> collections.Callable[[_CommandT], _CommandT]: """Add an option to a message command through a decorator call. @@ -1352,10 +1341,10 @@ def with_multi_option( converters: _MaybeIterable[ConverterSig[str]] = (), default: typing.Any, empty_value: typing.Any = tanjun.NO_DEFAULT, - min_length: typing.Optional[int] = None, - max_length: typing.Optional[int] = None, - min_value: typing.Optional[_CmpProto[str]] = None, - max_value: typing.Optional[_CmpProto[str]] = None, + min_length: int | None = None, + max_length: int | None = None, + min_value: _CmpProto[str] | None = None, + max_value: _CmpProto[str] | None = None, ) -> collections.Callable[[_CommandT], _CommandT]: ... @@ -1368,10 +1357,10 @@ def with_multi_option( converters: _MaybeIterable[ConverterSig[_SizedCmpProtoT]], default: typing.Any, empty_value: typing.Any = tanjun.NO_DEFAULT, - min_length: typing.Optional[int] = None, - max_length: typing.Optional[int] = None, - min_value: typing.Optional[_SizedCmpProtoT] = None, - max_value: typing.Optional[_SizedCmpProtoT] = None, + min_length: int | None = None, + max_length: int | None = None, + min_value: _SizedCmpProtoT | None = None, + max_value: _SizedCmpProtoT | None = None, ) -> collections.Callable[[_CommandT], _CommandT]: ... @@ -1384,8 +1373,8 @@ def with_multi_option( converters: _MaybeIterable[ConverterSig[collections.Sized]], default: typing.Any, empty_value: typing.Any = tanjun.NO_DEFAULT, - min_length: typing.Optional[int] = None, - max_length: typing.Optional[int] = None, + min_length: int | None = None, + max_length: int | None = None, ) -> collections.Callable[[_CommandT], _CommandT]: ... @@ -1398,8 +1387,8 @@ def with_multi_option( converters: _MaybeIterable[ConverterSig[_CmpProtoT]], default: typing.Any, empty_value: typing.Any = tanjun.NO_DEFAULT, - min_value: typing.Optional[_CmpProtoT] = None, - max_value: typing.Optional[_CmpProtoT] = None, + min_value: _CmpProtoT | None = None, + max_value: _CmpProtoT | None = None, ) -> collections.Callable[[_CommandT], _CommandT]: ... @@ -1411,10 +1400,10 @@ def with_multi_option( converters: _MaybeIterable[ConverterSig[typing.Any]] = (), default: typing.Any, empty_value: typing.Any = tanjun.NO_DEFAULT, - min_length: typing.Optional[int] = None, - max_length: typing.Optional[int] = None, - min_value: typing.Optional[typing.Any] = None, - max_value: typing.Optional[typing.Any] = None, + min_length: int | None = None, + max_length: int | None = None, + min_value: typing.Any | None = None, + max_value: typing.Any | None = None, ) -> collections.Callable[[_CommandT], _CommandT]: """Add an multi-option to a command's parser through a decorator call. @@ -1537,15 +1526,15 @@ def __init__( *, converters: _MaybeIterable[ConverterSig[typing.Any]] = (), default: typing.Any = tanjun.NO_DEFAULT, - min_length: typing.Optional[int] = None, - max_length: typing.Optional[int] = None, - min_value: typing.Optional[_CmpProto[typing.Any]] = None, - max_value: typing.Optional[_CmpProto[typing.Any]] = None, + min_length: int | None = None, + max_length: int | None = None, + min_value: _CmpProto[typing.Any] | None = None, + max_value: _CmpProto[typing.Any] | None = None, multi: bool = False, ) -> None: """Initialise a parameter.""" - self._client: typing.Optional[tanjun.Client] = None - self._component: typing.Optional[tanjun.Component] = None + self._client: tanjun.Client | None = None + self._component: tanjun.Component | None = None self._converters: list[ConverterSig[typing.Any]] = [] self._default = default self._is_multi = multi @@ -1595,7 +1584,7 @@ def is_multi(self) -> bool: return self._is_multi @property - def min_length(self) -> typing.Optional[int]: + def min_length(self) -> int | None: """If set, this parameters's parsed values will have to have lengths greater than or equal to this. If any converters are provided then this should be compatible with the @@ -1604,7 +1593,7 @@ def min_length(self) -> typing.Optional[int]: return self._min_length @property - def max_length(self) -> typing.Optional[int]: + def max_length(self) -> int | None: """If set, this parameters's parsed values will have to have lengths less than or equal to this. If any converters are provided then this should be compatible with the @@ -1613,7 +1602,7 @@ def max_length(self) -> typing.Optional[int]: return self._max_length @property - def min_value(self) -> typing.Optional[_CmpProto[typing.Any]]: + def min_value(self) -> _CmpProto[typing.Any] | None: """If set, this parameters's parsed values will have to be greater than or equal to this. If any converters are provided then this should be compatible with the @@ -1622,7 +1611,7 @@ def min_value(self) -> typing.Optional[_CmpProto[typing.Any]]: return self._min_value @property - def max_value(self) -> typing.Optional[_CmpProto[typing.Any]]: + def max_value(self) -> _CmpProto[typing.Any] | None: """If set, this parameters's parsed values will have to be less than or equal to this. If any converters are provided then this should be compatible with the @@ -1665,7 +1654,7 @@ def _validate(self, value: typing.Any, /) -> None: if self._max_value is not None and self._max_value < value: raise errors.ConversionError(f"{self._key!r} must be less than or equal to {self._max_value!r}", self._key) - length: typing.Optional[int] = None + length: int | None = None # asserts that len(value) >= self._min_length if self._min_length is not None and self._min_length > (length := len(value)): raise errors.ConversionError(f"{self._key!r} must be longer than {self._min_length - 1}", self._key) @@ -1721,10 +1710,10 @@ def __init__( converters: _MaybeIterable[ConverterSig[typing.Any]] = (), default: typing.Any = tanjun.NO_DEFAULT, greedy: bool = False, - min_length: typing.Optional[int] = None, - max_length: typing.Optional[int] = None, - min_value: typing.Optional[_CmpProto[typing.Any]] = None, - max_value: typing.Optional[_CmpProto[typing.Any]] = None, + min_length: int | None = None, + max_length: int | None = None, + min_value: _CmpProto[typing.Any] | None = None, + max_value: _CmpProto[typing.Any] | None = None, multi: bool = False, ) -> None: """Initialise a positional argument. @@ -1816,10 +1805,10 @@ def __init__( converters: _MaybeIterable[ConverterSig[typing.Any]] = (), default: typing.Any, empty_value: typing.Any = tanjun.NO_DEFAULT, - min_length: typing.Optional[int] = None, - max_length: typing.Optional[int] = None, - min_value: typing.Optional[_CmpProto[typing.Any]] = None, - max_value: typing.Optional[_CmpProto[typing.Any]] = None, + min_length: int | None = None, + max_length: int | None = None, + min_value: _CmpProto[typing.Any] | None = None, + max_value: _CmpProto[typing.Any] | None = None, multi: bool = True, ) -> None: """Initialise a named optional parameter. @@ -1918,8 +1907,8 @@ def __init__(self) -> None: """Initialise a shlex parser.""" self._arguments: list[Argument] = [] self._callback_arg_names: list[tuple[str, collections.Container[str]]] = [] - self._client: typing.Optional[tanjun.Client] = None - self._component: typing.Optional[tanjun.Component] = None + self._client: tanjun.Client | None = None + self._component: tanjun.Component | None = None self._options: list[Option] = [] # TODO: maybe switch to dict[str, Option] and assert doesn't already exist @property @@ -1965,10 +1954,10 @@ def add_argument( *, default: typing.Any = tanjun.NO_DEFAULT, greedy: bool = False, - min_length: typing.Optional[int] = None, - max_length: typing.Optional[int] = None, - min_value: typing.Optional[_CmpProto[str]] = None, - max_value: typing.Optional[_CmpProto[str]] = None, + min_length: int | None = None, + max_length: int | None = None, + min_value: _CmpProto[str] | None = None, + max_value: _CmpProto[str] | None = None, multi: bool = False, ) -> Self: ... @@ -1981,10 +1970,10 @@ def add_argument( *, default: typing.Any = tanjun.NO_DEFAULT, greedy: bool = False, - min_length: typing.Optional[int] = None, - max_length: typing.Optional[int] = None, - min_value: typing.Optional[_SizedCmpProtoT] = None, - max_value: typing.Optional[_SizedCmpProtoT] = None, + min_length: int | None = None, + max_length: int | None = None, + min_value: _SizedCmpProtoT | None = None, + max_value: _SizedCmpProtoT | None = None, multi: bool = False, ) -> Self: ... @@ -1997,8 +1986,8 @@ def add_argument( *, default: typing.Any = tanjun.NO_DEFAULT, greedy: bool = False, - min_length: typing.Optional[int] = None, - max_length: typing.Optional[int] = None, + min_length: int | None = None, + max_length: int | None = None, multi: bool = False, ) -> Self: ... @@ -2011,8 +2000,8 @@ def add_argument( *, default: typing.Any = tanjun.NO_DEFAULT, greedy: bool = False, - min_value: typing.Optional[_CmpProtoT] = None, - max_value: typing.Optional[_CmpProtoT] = None, + min_value: _CmpProtoT | None = None, + max_value: _CmpProtoT | None = None, multi: bool = False, ) -> Self: ... @@ -2024,10 +2013,10 @@ def add_argument( *, default: typing.Any = tanjun.NO_DEFAULT, greedy: bool = False, - min_length: typing.Optional[int] = None, - max_length: typing.Optional[int] = None, - min_value: typing.Optional[typing.Any] = None, - max_value: typing.Optional[typing.Any] = None, + min_length: int | None = None, + max_length: int | None = None, + min_value: typing.Any | None = None, + max_value: typing.Any | None = None, multi: bool = False, ) -> Self: # <>. @@ -2079,10 +2068,10 @@ def add_option( converters: _MaybeIterable[ConverterSig[str]] = (), default: typing.Any, empty_value: typing.Any = tanjun.NO_DEFAULT, - min_length: typing.Optional[int] = None, - max_length: typing.Optional[int] = None, - min_value: typing.Optional[_CmpProto[str]] = None, - max_value: typing.Optional[_CmpProto[str]] = None, + min_length: int | None = None, + max_length: int | None = None, + min_value: _CmpProto[str] | None = None, + max_value: _CmpProto[str] | None = None, multi: bool = False, ) -> Self: ... @@ -2096,10 +2085,10 @@ def add_option( converters: _MaybeIterable[ConverterSig[_SizedCmpProtoT]], default: typing.Any, empty_value: typing.Any = tanjun.NO_DEFAULT, - min_length: typing.Optional[int] = None, - max_length: typing.Optional[int] = None, - min_value: typing.Optional[_SizedCmpProtoT] = None, - max_value: typing.Optional[_SizedCmpProtoT] = None, + min_length: int | None = None, + max_length: int | None = None, + min_value: _SizedCmpProtoT | None = None, + max_value: _SizedCmpProtoT | None = None, multi: bool = False, ) -> Self: ... @@ -2113,8 +2102,8 @@ def add_option( converters: _MaybeIterable[ConverterSig[collections.Sized]], default: typing.Any, empty_value: typing.Any = tanjun.NO_DEFAULT, - min_length: typing.Optional[int] = None, - max_length: typing.Optional[int] = None, + min_length: int | None = None, + max_length: int | None = None, multi: bool = False, ) -> Self: ... @@ -2128,8 +2117,8 @@ def add_option( converters: _MaybeIterable[ConverterSig[_CmpProtoT]], default: typing.Any, empty_value: typing.Any = tanjun.NO_DEFAULT, - min_value: typing.Optional[_CmpProtoT] = None, - max_value: typing.Optional[_CmpProtoT] = None, + min_value: _CmpProtoT | None = None, + max_value: _CmpProtoT | None = None, multi: bool = False, ) -> Self: ... @@ -2143,10 +2132,10 @@ def add_option( converters: _MaybeIterable[ConverterSig[typing.Any]] = (), default: typing.Any, empty_value: typing.Any = tanjun.NO_DEFAULT, - min_length: typing.Optional[int] = None, - max_length: typing.Optional[int] = None, - min_value: typing.Optional[typing.Any] = None, - max_value: typing.Optional[typing.Any] = None, + min_length: int | None = None, + max_length: int | None = None, + min_value: typing.Any | None = None, + max_value: typing.Any | None = None, multi: bool = False, ) -> Self: # <>. diff --git a/tanjun/permissions.py b/tanjun/permissions.py index 7293c234d..952fd5f7f 100644 --- a/tanjun/permissions.py +++ b/tanjun/permissions.py @@ -113,7 +113,7 @@ def calculate_permissions( roles: collections.Mapping[hikari.Snowflake, hikari.Role], /, *, - channel: typing.Optional[hikari.PermissibleGuildChannel] = None, + channel: hikari.PermissibleGuildChannel | None = None, ) -> hikari.Permissions: """Calculate the permissions a member has within a guild. @@ -179,7 +179,7 @@ async def fetch_permissions( member: hikari.Member, /, *, - channel: typing.Optional[hikari.SnowflakeishOr[hikari.GuildChannel]] = None, + channel: hikari.SnowflakeishOr[hikari.GuildChannel] | None = None, ) -> hikari.Permissions: """Calculate the permissions a member has within a guild. @@ -205,8 +205,8 @@ async def fetch_permissions( """ # The ordering of how this adds and removes permissions does matter. # For more information see https://discord.com/developers/docs/topics/permissions#permission-hierarchy. - guild: typing.Optional[hikari.Guild] - roles: typing.Optional[collections.Mapping[hikari.Snowflake, hikari.Role]] = None + guild: hikari.Guild | None + roles: collections.Mapping[hikari.Snowflake, hikari.Role] | None = None guild = client.cache.get_guild(member.guild_id) if client.cache else None if not guild: # noqa: SIM102 # Has to be nested cause of pyright bug. @@ -253,7 +253,7 @@ async def fetch_permissions( def calculate_everyone_permissions( - everyone_role: hikari.Role, /, *, channel: typing.Optional[hikari.PermissibleGuildChannel] = None + everyone_role: hikari.Role, /, *, channel: hikari.PermissibleGuildChannel | None = None ) -> hikari.Permissions: """Calculate a guild's default permissions within the guild or for a specific channel. @@ -294,7 +294,7 @@ async def fetch_everyone_permissions( guild_id: hikari.Snowflake, /, *, - channel: typing.Optional[hikari.SnowflakeishOr[hikari.GuildChannel]] = None, + channel: hikari.SnowflakeishOr[hikari.GuildChannel] | None = None, ) -> hikari.Permissions: """Calculate the permissions a guild's default @everyone role has within a guild or for a specific channel. diff --git a/tanjun/schedules.py b/tanjun/schedules.py index 268025840..d287181fb 100644 --- a/tanjun/schedules.py +++ b/tanjun/schedules.py @@ -47,9 +47,9 @@ from . import components if typing.TYPE_CHECKING: - import typing_extensions + from typing import Self + from alluka import abc as alluka - from typing_extensions import Self from . import abc as tanjun @@ -94,7 +94,7 @@ def copy(self) -> Self: """ @abc.abstractmethod - def start(self, client: alluka.Client, /, *, loop: typing.Optional[asyncio.AbstractEventLoop] = None) -> None: + def start(self, client: alluka.Client, /, *, loop: asyncio.AbstractEventLoop | None = None) -> None: """Start the schedule. Parameters @@ -138,7 +138,7 @@ def add_schedule(self, schedule: AbstractSchedule, /) -> typing.Any: raise NotImplementedError -def _is_component_proto(value: typing.Any, /) -> typing_extensions.TypeGuard[_ComponentProto]: +def _is_component_proto(value: typing.Any, /) -> typing.TypeGuard[_ComponentProto]: try: value.add_schedule @@ -149,12 +149,12 @@ def _is_component_proto(value: typing.Any, /) -> typing_extensions.TypeGuard[_Co def as_interval( - interval: typing.Union[int, float, datetime.timedelta], + interval: int | float | datetime.timedelta, /, *, fatal_exceptions: collections.Sequence[type[Exception]] = (), ignored_exceptions: collections.Sequence[type[Exception]] = (), - max_runs: typing.Optional[int] = None, + max_runs: int | None = None, ) -> collections.Callable[[_CallbackSigT], IntervalSchedule[_CallbackSigT]]: """Decorator to create an schedule. @@ -226,12 +226,12 @@ class IntervalSchedule(typing.Generic[_CallbackSigT], components.AbstractCompone def __init__( self, callback: _CallbackSigT, - interval: typing.Union[datetime.timedelta, int, float], + interval: datetime.timedelta | int | float, /, *, fatal_exceptions: collections.Sequence[type[Exception]] = (), ignored_exceptions: collections.Sequence[type[Exception]] = (), - max_runs: typing.Optional[int] = None, + max_runs: int | None = None, ) -> None: """Initialise an interval schedule. @@ -259,14 +259,14 @@ def __init__( self._interval = datetime.timedelta(seconds=interval) self._callback = callback - self._client: typing.Optional[alluka.Client] = None + self._client: alluka.Client | None = None self._fatal_exceptions = tuple(fatal_exceptions) self._ignored_exceptions = tuple(ignored_exceptions) self._iteration_count: int = 0 self._max_runs = max_runs - self._stop_callback: typing.Optional[_CallbackSig] = None - self._start_callback: typing.Optional[_CallbackSig] = None - self._task: typing.Optional[asyncio.Task[None]] = None + self._stop_callback: _CallbackSig | None = None + self._start_callback: _CallbackSig | None = None + self._task: asyncio.Task[None] | None = None self._tasks: list[asyncio.Task[None]] = [] @property @@ -402,7 +402,7 @@ async def _on_stop(self, client: alluka.Client, /) -> None: except Exception: traceback.print_exc() - def start(self, client: alluka.Client, /, *, loop: typing.Optional[asyncio.AbstractEventLoop] = None) -> None: + def start(self, client: alluka.Client, /, *, loop: asyncio.AbstractEventLoop | None = None) -> None: # <>. if self._task: raise RuntimeError("Cannot start an active schedule") @@ -557,7 +557,7 @@ def set_fatal_exceptions(self, *exceptions: type[Exception]) -> Self: return self -def _get_next(target_values: collections.Sequence[int], current_value: int, /) -> typing.Optional[int]: +def _get_next(target_values: collections.Sequence[int], current_value: int, /) -> int | None: for value in target_values: if value > current_value: return value @@ -566,8 +566,8 @@ def _get_next(target_values: collections.Sequence[int], current_value: int, /) - def _to_sequence( - values: typing.Union[int, collections.Sequence[int], None], min_: int, max_: int, name: str, / -) -> typing.Optional[collections.Sequence[int]]: + values: int | collections.Sequence[int] | None, min_: int, max_: int, name: str, / +) -> collections.Sequence[int] | None: if values is None: return None @@ -609,13 +609,13 @@ class _TimeScheduleConfig: __slots__ = ("current_date", "days", "hours", "is_weekly", "minutes", "months", "seconds", "timezone") current_date: datetime.datetime - days: typing.Optional[collections.Sequence[int]] + days: collections.Sequence[int] | None hours: collections.Sequence[int] is_weekly: bool minutes: collections.Sequence[int] months: collections.Sequence[int] seconds: collections.Sequence[int] - timezone: typing.Optional[datetime.timezone] + timezone: datetime.timezone | None class _Datetime: @@ -720,7 +720,7 @@ def _next_day(self) -> Self: current = self._date.year, self._date.month if day is None: # Indicates we've passed the last matching day in this week. # This handles flowing to the next month/year. - self._date = (self._date + datetime.timedelta((8 - self._date.isoweekday()))).replace( + self._date = (self._date + datetime.timedelta(8 - self._date.isoweekday())).replace( hour=0, minute=0, second=0 ) # Then recalculate @@ -798,15 +798,15 @@ def _next_second(self) -> Self: def as_time_schedule( *, - months: typing.Union[int, collections.Sequence[int]] = (), + months: int | collections.Sequence[int] = (), weekly: bool = False, - days: typing.Union[int, collections.Sequence[int]] = (), - hours: typing.Union[int, collections.Sequence[int]] = (), - minutes: typing.Union[int, collections.Sequence[int]] = (), - seconds: typing.Union[int, collections.Sequence[int]] = 0, + days: int | collections.Sequence[int] = (), + hours: int | collections.Sequence[int] = (), + minutes: int | collections.Sequence[int] = (), + seconds: int | collections.Sequence[int] = 0, fatal_exceptions: collections.Sequence[type[Exception]] = (), ignored_exceptions: collections.Sequence[type[Exception]] = (), - timezone: typing.Optional[datetime.timezone] = None, + timezone: datetime.timezone | None = None, ) -> collections.Callable[[_CallbackSigT], TimeSchedule[_CallbackSigT]]: """Create a time schedule through a decorator call. @@ -926,15 +926,15 @@ def __init__( callback: _CallbackSigT, /, *, - months: typing.Union[int, collections.Sequence[int]] = (), + months: int | collections.Sequence[int] = (), weekly: bool = False, - days: typing.Union[int, collections.Sequence[int]] = (), - hours: typing.Union[int, collections.Sequence[int]] = (), - minutes: typing.Union[int, collections.Sequence[int]] = (), - seconds: typing.Union[int, collections.Sequence[int]] = 0, + days: int | collections.Sequence[int] = (), + hours: int | collections.Sequence[int] = (), + minutes: int | collections.Sequence[int] = (), + seconds: int | collections.Sequence[int] = 0, fatal_exceptions: collections.Sequence[type[Exception]] = (), ignored_exceptions: collections.Sequence[type[Exception]] = (), - timezone: typing.Optional[datetime.timezone] = None, + timezone: datetime.timezone | None = None, ) -> None: """Initialise the time schedule. @@ -1023,7 +1023,7 @@ def __init__( ) self._fatal_exceptions = tuple(fatal_exceptions) self._ignored_exceptions = tuple(ignored_exceptions) - self._task: typing.Optional[asyncio.Task[None]] = None + self._task: asyncio.Task[None] | None = None self._tasks: list[asyncio.Task[None]] = [] @property @@ -1096,7 +1096,7 @@ def load_into_component(self, component: tanjun.Component, /) -> None: if _is_component_proto(component): component.add_schedule(self) - def start(self, client: alluka.Client, /, *, loop: typing.Optional[asyncio.AbstractEventLoop] = None) -> None: + def start(self, client: alluka.Client, /, *, loop: asyncio.AbstractEventLoop | None = None) -> None: # <>. if self._task: raise RuntimeError("Schedule is already running") diff --git a/tests/commands/test_base.py b/tests/commands/test_base.py index ed79c075e..d5567816f 100644 --- a/tests/commands/test_base.py +++ b/tests/commands/test_base.py @@ -50,7 +50,7 @@ def stub_class( cls: type[_T], /, args: collections.Sequence[typing.Any] = (), - kwargs: typing.Optional[collections.Mapping[str, typing.Any]] = None, + kwargs: collections.Mapping[str, typing.Any] | None = None, **namespace: typing.Any, ) -> _T: namespace["__slots__"] = () diff --git a/tests/commands/test_menu.py b/tests/commands/test_menu.py index c455718d3..bf72d3192 100644 --- a/tests/commands/test_menu.py +++ b/tests/commands/test_menu.py @@ -98,9 +98,9 @@ def test_as_message_menu_with_defaults(): ], ) def test_as_message_menu_when_wrapping_command( - other_command: typing.Union[ - tanjun.SlashCommand[typing.Any], tanjun.MessageCommand[typing.Any], tanjun.MenuCommand[typing.Any, typing.Any] - ] + other_command: ( + tanjun.SlashCommand[typing.Any] | tanjun.MessageCommand[typing.Any] | tanjun.MenuCommand[typing.Any, typing.Any] + ) ): command = tanjun.as_message_menu( "c", @@ -178,9 +178,9 @@ def test_as_user_menu_with_defaults(): ], ) def test_as_user_menu_when_wrapping_command( - other_command: typing.Union[ - tanjun.SlashCommand[typing.Any], tanjun.MessageCommand[typing.Any], tanjun.MenuCommand[typing.Any, typing.Any] - ] + other_command: ( + tanjun.SlashCommand[typing.Any] | tanjun.MessageCommand[typing.Any] | tanjun.MenuCommand[typing.Any, typing.Any] + ) ): command = tanjun.as_user_menu( "c", @@ -259,11 +259,11 @@ def test__init__when_localised_default_name_too_short(self): ) def test___init___when_command_object( self, - inner_command: typing.Union[ - tanjun.SlashCommand[tanjun.abc.CommandCallbackSig], - tanjun.MessageCommand[tanjun.abc.CommandCallbackSig], - tanjun.MenuCommand[typing.Any, typing.Any], - ], + inner_command: ( + tanjun.SlashCommand[tanjun.abc.CommandCallbackSig] + | tanjun.MessageCommand[tanjun.abc.CommandCallbackSig] + | tanjun.MenuCommand[typing.Any, typing.Any] + ), ): assert tanjun.MenuCommand(inner_command, hikari.CommandType.MESSAGE, "woow").callback is inner_command.callback diff --git a/tests/commands/test_message.py b/tests/commands/test_message.py index 1b54a2f44..44278bad7 100644 --- a/tests/commands/test_message.py +++ b/tests/commands/test_message.py @@ -54,7 +54,7 @@ def stub_class( cls: type[_T], /, args: collections.Sequence[typing.Any] = (), - kwargs: typing.Optional[collections.Mapping[str, typing.Any]] = None, + kwargs: collections.Mapping[str, typing.Any] | None = None, **namespace: typing.Any, ) -> _T: namespace["__slots__"] = () @@ -87,9 +87,9 @@ def test_as_message_command(): ], ) def test_as_message_command_when_wrapping_command( - other_command: typing.Union[ - tanjun.SlashCommand[typing.Any], tanjun.MessageCommand[typing.Any], tanjun.MenuCommand[typing.Any, typing.Any] - ] + other_command: ( + tanjun.SlashCommand[typing.Any] | tanjun.MessageCommand[typing.Any] | tanjun.MenuCommand[typing.Any, typing.Any] + ) ): command = tanjun.as_message_command("a", "b")(other_command) @@ -117,9 +117,9 @@ def test_as_message_command_group(): ], ) def test_as_message_command_group_when_wrapping_command( - other_command: typing.Union[ - tanjun.SlashCommand[typing.Any], tanjun.MessageCommand[typing.Any], tanjun.MenuCommand[typing.Any, typing.Any] - ] + other_command: ( + tanjun.SlashCommand[typing.Any] | tanjun.MessageCommand[typing.Any] | tanjun.MenuCommand[typing.Any, typing.Any] + ) ): command = tanjun.as_message_command_group("c", "b", strict=True)(other_command) @@ -138,9 +138,7 @@ class TestMessageCommand: ) def test___init___when_command_object( self, - inner_command: typing.Union[ - tanjun.SlashCommand[tanjun.abc.CommandCallbackSig], tanjun.MenuCommand[typing.Any, typing.Any] - ], + inner_command: tanjun.SlashCommand[tanjun.abc.CommandCallbackSig] | tanjun.MenuCommand[typing.Any, typing.Any], ): assert tanjun.MessageCommand(inner_command, "woow").callback is inner_command.callback diff --git a/tests/commands/test_slash.py b/tests/commands/test_slash.py index 8d117a276..193082fcc 100644 --- a/tests/commands/test_slash.py +++ b/tests/commands/test_slash.py @@ -56,7 +56,7 @@ def stub_class( cls: type[_T], /, args: collections.Sequence[typing.Any] = (), - kwargs: typing.Optional[collections.Mapping[str, typing.Any]] = None, + kwargs: collections.Mapping[str, typing.Any] | None = None, **namespace: typing.Any, ) -> _T: namespace["__slots__"] = () @@ -141,9 +141,9 @@ def test_as_slash_command(): ], ) def test_as_slash_command_when_wrapping_command( - other_command: typing.Union[ - tanjun.SlashCommand[typing.Any], tanjun.MessageCommand[typing.Any], tanjun.MenuCommand[typing.Any, typing.Any] - ] + other_command: ( + tanjun.SlashCommand[typing.Any] | tanjun.MessageCommand[typing.Any] | tanjun.MenuCommand[typing.Any, typing.Any] + ) ): command = tanjun.as_slash_command( "a_very", @@ -1336,11 +1336,11 @@ class TestSlashCommand: ) def test___init___when_command_object( self, - inner_command: typing.Union[ - tanjun.SlashCommand[tanjun.abc.CommandCallbackSig], - tanjun.MessageCommand[tanjun.abc.CommandCallbackSig], - tanjun.MenuCommand[typing.Any, typing.Any], - ], + inner_command: ( + tanjun.SlashCommand[tanjun.abc.CommandCallbackSig] + | tanjun.MessageCommand[tanjun.abc.CommandCallbackSig] + | tanjun.MenuCommand[typing.Any, typing.Any] + ), ): assert tanjun.SlashCommand(inner_command, "woow", "no").callback is inner_command.callback @@ -2875,8 +2875,8 @@ def test_add_channel_option_with_defaults(self, command: tanjun.SlashCommand[typ def test_add_channel_option_types_behaviour( self, command: tanjun.SlashCommand[typing.Any], - classes: list[typing.Union[type[hikari.PartialChannel], int]], - int_types: typing.Optional[list[int]], + classes: list[type[hikari.PartialChannel] | int], + int_types: list[int] | None, ): command.add_channel_option("channel", "chaaa", types=classes) diff --git a/tests/context/test_base.py b/tests/context/test_base.py index 3cba50530..9b10db387 100644 --- a/tests/context/test_base.py +++ b/tests/context/test_base.py @@ -53,7 +53,7 @@ def stub_class( cls: type[_T], /, args: collections.Sequence[typing.Any] = (), - kwargs: typing.Optional[collections.Mapping[str, typing.Any]] = None, + kwargs: collections.Mapping[str, typing.Any] | None = None, **namespace: typing.Any, ) -> _T: namespace["__slots__"] = () diff --git a/tests/context/test_message.py b/tests/context/test_message.py index 59584e11a..e92da8f42 100644 --- a/tests/context/test_message.py +++ b/tests/context/test_message.py @@ -53,7 +53,7 @@ def stub_class( cls: type[_T], /, args: collections.Sequence[typing.Any] = (), - kwargs: typing.Optional[collections.Mapping[str, typing.Any]] = None, + kwargs: collections.Mapping[str, typing.Any] | None = None, **namespace: typing.Any, ) -> _T: namespace["__slots__"] = () @@ -312,7 +312,7 @@ async def test_edit_initial_response_when_no_initial_response( @pytest.mark.parametrize("delete_after", [datetime.timedelta(seconds=123), 123, 123.0]) @pytest.mark.asyncio async def test_edit_initial_response_when_delete_after( - self, delete_after: typing.Union[datetime.timedelta, float, int], mock_client: mock.Mock + self, delete_after: datetime.timedelta | float | int, mock_client: mock.Mock ): mock_register_task = mock.Mock() mock_delete_after = mock.Mock() @@ -389,7 +389,7 @@ async def test_edit_last_response_when_no_last_response( @pytest.mark.parametrize("delete_after", [datetime.timedelta(seconds=654), 654, 654.0]) @pytest.mark.asyncio async def test_edit_last_response_when_delete_after( - self, mock_client: mock.Mock, delete_after: typing.Union[datetime.timedelta, int, float] + self, mock_client: mock.Mock, delete_after: datetime.timedelta | int | float ): mock_register_task = mock.Mock() mock_delete_after = mock.Mock() @@ -534,7 +534,7 @@ async def test_respond_when_initial_response_id_already_set(self, context: tanju @pytest.mark.parametrize("delete_after", [datetime.timedelta(seconds=123), 123, 123.0]) @pytest.mark.asyncio - async def test_respond_when_delete_after(self, delete_after: typing.Union[int, float, datetime.timedelta]): + async def test_respond_when_delete_after(self, delete_after: int | float | datetime.timedelta): mock_delete_after = mock.Mock() mock_register_task = mock.Mock() context = stub_class( diff --git a/tests/context/test_slash.py b/tests/context/test_slash.py index e7fb4afbd..45978b9e7 100644 --- a/tests/context/test_slash.py +++ b/tests/context/test_slash.py @@ -53,7 +53,7 @@ def stub_class( cls: type[_T], /, args: collections.Sequence[typing.Any] = (), - kwargs: typing.Optional[collections.Mapping[str, typing.Any]] = None, + kwargs: collections.Mapping[str, typing.Any] | None = None, **namespace: typing.Any, ) -> _T: namespace["__slots__"] = () @@ -874,7 +874,7 @@ async def test_edit_initial_response(self, mock_client: mock.Mock): @pytest.mark.parametrize("delete_after", [datetime.timedelta(seconds=545), 545, 545.0]) @pytest.mark.asyncio async def test_edit_initial_response_when_delete_after( - self, mock_client: mock.Mock, delete_after: typing.Union[datetime.timedelta, int, float] + self, mock_client: mock.Mock, delete_after: datetime.timedelta | int | float ): mock_delete_initial_response_after = mock.Mock() mock_interaction = mock.AsyncMock(created_at=datetime.datetime.now(tz=datetime.timezone.utc)) @@ -898,7 +898,7 @@ async def test_edit_initial_response_when_delete_after( @pytest.mark.parametrize("delete_after", [datetime.timedelta(seconds=901), 901, 901.0]) @pytest.mark.asyncio async def test_edit_initial_response_when_delete_after_will_have_expired( - self, mock_client: mock.Mock, delete_after: typing.Union[datetime.timedelta, int, float] + self, mock_client: mock.Mock, delete_after: datetime.timedelta | int | float ): mock_delete_initial_response_after = mock.Mock() mock_register_task = mock.Mock() @@ -983,7 +983,7 @@ def context(self, mock_client: mock.Mock) -> tanjun.context.SlashContext: @pytest.mark.parametrize("raw_options", [None, []]) def test_options_property_when_no_options( - self, mock_client: mock.Mock, raw_options: typing.Optional[list[hikari.OptionType]] + self, mock_client: mock.Mock, raw_options: list[hikari.OptionType] | None ): context = tanjun.context.SlashContext( mock_client, mock.Mock(type=hikari.OptionType.SUB_COMMAND, options=raw_options), mock.Mock() @@ -1032,7 +1032,7 @@ def test_options_property_for_command_group(self, mock_client: mock.Mock): @pytest.mark.parametrize("raw_options", [None, []]) def test_options_property_for_command_group_with_no_sub_option( - self, mock_client: mock.Mock, raw_options: typing.Optional[list[hikari.OptionType]] + self, mock_client: mock.Mock, raw_options: list[hikari.OptionType] | None ): group_option = mock.Mock(type=hikari.OptionType.SUB_COMMAND, options=raw_options) context = tanjun.context.SlashContext(mock_client, mock.Mock(options=[group_option]), mock.Mock()) @@ -1061,7 +1061,7 @@ def test_options_property_for_sub_command_group(self, mock_client: mock.Mock): @pytest.mark.parametrize("raw_options", [None, []]) def test_options_property_for_sub_command_group_with_no_sub_option( - self, mock_client: mock.Mock, raw_options: typing.Optional[list[hikari.OptionType]] + self, mock_client: mock.Mock, raw_options: list[hikari.OptionType] | None ): sub_group_option = mock.Mock(type=hikari.OptionType.SUB_COMMAND, options=raw_options) group_option = mock.Mock(type=hikari.OptionType.SUB_COMMAND_GROUP, options=[sub_group_option]) diff --git a/tests/dependencies/test_data.py b/tests/dependencies/test_data.py index 46b8c9128..a57bb3873 100644 --- a/tests/dependencies/test_data.py +++ b/tests/dependencies/test_data.py @@ -121,7 +121,7 @@ def test_inject_lc(): @pytest.mark.parametrize("expire_after", [0.0, -1, datetime.timedelta(seconds=-2)]) -def test_cache_callback_when_invalid_expire_after(expire_after: typing.Union[float, int, datetime.timedelta]): +def test_cache_callback_when_invalid_expire_after(expire_after: float | int | datetime.timedelta): with pytest.raises(ValueError, match="expire_after must be more than 0 seconds"): tanjun.dependencies.data.cache_callback(mock.Mock(), expire_after=expire_after) @@ -150,7 +150,7 @@ async def test_cache_callback(): @pytest.mark.parametrize("expire_after", [4, 4.0, datetime.timedelta(seconds=4)]) @pytest.mark.asyncio -async def test_cache_callback_when_expired(expire_after: typing.Union[float, int, datetime.timedelta]): +async def test_cache_callback_when_expired(expire_after: float | int | datetime.timedelta): mock_callback = mock.AsyncMock() mock_first_context = mock.AsyncMock() mock_second_context = mock.AsyncMock() @@ -180,7 +180,7 @@ async def test_cache_callback_when_expired(expire_after: typing.Union[float, int @pytest.mark.parametrize("expire_after", [15, 15.0, datetime.timedelta(seconds=15)]) @pytest.mark.asyncio -async def test_cache_callback_when_not_expired(expire_after: typing.Union[float, int, datetime.timedelta]): +async def test_cache_callback_when_not_expired(expire_after: float | int | datetime.timedelta): mock_callback = mock.AsyncMock() mock_context = mock.AsyncMock() cached_callback = tanjun.dependencies.data.cache_callback(mock_callback, expire_after=expire_after) diff --git a/tests/dependencies/test_limiters.py b/tests/dependencies/test_limiters.py index f71041041..9225b0e2d 100644 --- a/tests/dependencies/test_limiters.py +++ b/tests/dependencies/test_limiters.py @@ -1661,9 +1661,7 @@ def test_set_bucket(self, resource_type: tanjun.BucketResource): assert cooldown.reset_after == datetime.timedelta(seconds=43, milliseconds=123) @pytest.mark.parametrize("reset_after", [datetime.timedelta(seconds=69), 69, 69.0]) - def test_set_bucket_handles_different_reset_after_types( - self, reset_after: typing.Union[datetime.timedelta, int, float] - ): + def test_set_bucket_handles_different_reset_after_types(self, reset_after: datetime.timedelta | int | float): manager = tanjun.dependencies.InMemoryCooldownManager() with mock.patch.object(tanjun.dependencies.limiters, "_FlatResource") as cooldown_bucket: @@ -1742,7 +1740,7 @@ def test_set_bucket_when_is_default(self): assert cooldown.reset_after == datetime.timedelta(seconds=666) @pytest.mark.parametrize("reset_after", [datetime.timedelta(seconds=-42), -431, -0.123]) - def test_set_bucket_when_reset_after_is_negative(self, reset_after: typing.Union[datetime.timedelta, float, int]): + def test_set_bucket_when_reset_after_is_negative(self, reset_after: datetime.timedelta | float | int): manager = tanjun.dependencies.InMemoryCooldownManager() with pytest.raises(ValueError, match="reset_after must be greater than 0 seconds"): diff --git a/tests/dependencies/test_owners.py b/tests/dependencies/test_owners.py index 91a1f4c21..86e3be886 100644 --- a/tests/dependencies/test_owners.py +++ b/tests/dependencies/test_owners.py @@ -35,7 +35,6 @@ import asyncio import datetime import time -import typing import hikari import mock @@ -46,7 +45,7 @@ class TestOwners: @pytest.mark.parametrize("value", [0, -1.0, datetime.timedelta(seconds=-2)]) - def test_init_with_invalid_expire_after(self, value: typing.Union[int, float, datetime.timedelta]): + def test_init_with_invalid_expire_after(self, value: int | float | datetime.timedelta): with pytest.raises(ValueError, match="Expire after must be greater than 0 seconds"): tanjun.dependencies.Owners(expire_after=-1) @@ -273,9 +272,7 @@ async def test_check_ownership_application_caching_behaviour(self): @pytest.mark.parametrize("expire_after", [datetime.timedelta(seconds=60), 60, 60.0]) @pytest.mark.asyncio - async def test_check_ownership_application_expires_cache( - self, expire_after: typing.Union[float, int, datetime.timedelta] - ): + async def test_check_ownership_application_expires_cache(self, expire_after: float | int | datetime.timedelta): check = tanjun.dependencies.Owners(expire_after=expire_after) mock_client = mock.Mock(tanjun.Client) mock_client.get_type_dependency.return_value = None diff --git a/tests/test_annotations.py b/tests/test_annotations.py index 9af96d646..87a42e964 100644 --- a/tests/test_annotations.py +++ b/tests/test_annotations.py @@ -35,15 +35,13 @@ import enum import inspect import re -import sys import typing from collections import abc as collections +from unittest import mock import alluka import hikari -import mock import pytest -import typing_extensions import tanjun from tanjun import annotations @@ -4778,7 +4776,7 @@ async def command( assert tracked_option.type is hikari.OptionType.USER -def test_when_annotated_not_top_level(): +def test_when_annotated_not_top_level_typing_union(): @annotations.with_annotated_args(follow_wrapped=True) @tanjun.as_slash_command("name", "description") @tanjun.as_message_command("name") @@ -4850,81 +4848,79 @@ async def command( assert option.max_value is None -if sys.version_info >= (3, 10): +def test_when_annotated_not_top_level_3_10_union(): + @annotations.with_annotated_args(follow_wrapped=True) + @tanjun.as_slash_command("name", "description") + @tanjun.as_message_command("name") + async def command( + ctx: tanjun.abc.Context, + *, + value: typing.Annotated[annotations.Str, annotations.Positional(), "nyaa"] | bool = False, + other_value: typing.Annotated[annotations.Int, "meow"] | None = None, + ) -> None: + raise NotImplementedError - def test_when_annotated_not_top_level_3_10_union(): - @annotations.with_annotated_args(follow_wrapped=True) - @tanjun.as_slash_command("name", "description") - @tanjun.as_message_command("name") - async def command( - ctx: tanjun.abc.Context, - *, - value: typing.Annotated[annotations.Str, annotations.Positional(), "nyaa"] | bool = False, - other_value: typing.Annotated[annotations.Int, "meow"] | None = None, - ) -> None: - raise NotImplementedError - - assert command.build().options == [ - hikari.CommandOption(type=hikari.OptionType.STRING, name="value", description="nyaa", is_required=False), - hikari.CommandOption( - type=hikari.OptionType.INTEGER, - name="other_value", - description="meow", - is_required=False, - min_value=None, - max_value=None, - ), - ] + assert command.build().options == [ + hikari.CommandOption(type=hikari.OptionType.STRING, name="value", description="nyaa", is_required=False), + hikari.CommandOption( + type=hikari.OptionType.INTEGER, + name="other_value", + description="meow", + is_required=False, + min_value=None, + max_value=None, + ), + ] + + assert len(command._tracked_options) == 2 + tracked_option = command._tracked_options["value"] + assert tracked_option.converters == [] + assert tracked_option.default is tanjun.abc.NO_PASS + assert tracked_option.is_always_float is False + assert tracked_option.is_only_member is False + assert tracked_option.key == "value" + assert tracked_option.name == "value" + assert tracked_option.type is hikari.OptionType.STRING + + tracked_option = command._tracked_options["other_value"] + assert tracked_option.converters == [] + assert tracked_option.default is tanjun.abc.NO_PASS + assert tracked_option.is_always_float is False + assert tracked_option.is_only_member is False + assert tracked_option.key == "other_value" + assert tracked_option.name == "other_value" + assert tracked_option.type is hikari.OptionType.INTEGER + + assert isinstance(command.wrapped_command, tanjun.MessageCommand) + assert isinstance(command.wrapped_command.parser, tanjun.ShlexParser) - assert len(command._tracked_options) == 2 - tracked_option = command._tracked_options["value"] - assert tracked_option.converters == [] - assert tracked_option.default is tanjun.abc.NO_PASS - assert tracked_option.is_always_float is False - assert tracked_option.is_only_member is False - assert tracked_option.key == "value" - assert tracked_option.name == "value" - assert tracked_option.type is hikari.OptionType.STRING - - tracked_option = command._tracked_options["other_value"] - assert tracked_option.converters == [] - assert tracked_option.default is tanjun.abc.NO_PASS - assert tracked_option.is_always_float is False - assert tracked_option.is_only_member is False - assert tracked_option.key == "other_value" - assert tracked_option.name == "other_value" - assert tracked_option.type is hikari.OptionType.INTEGER - - assert isinstance(command.wrapped_command, tanjun.MessageCommand) - assert isinstance(command.wrapped_command.parser, tanjun.ShlexParser) - - assert len(command.wrapped_command.parser.arguments) == 1 - argument = command.wrapped_command.parser.arguments[0] - assert argument.key == "value" - assert argument.converters == [] - assert argument.default is tanjun.abc.NO_PASS - assert argument.is_greedy is False - assert argument.is_multi is False - assert argument.min_length is None - assert argument.max_length is None - assert argument.min_value is None - assert argument.max_value is None - - assert len(command.wrapped_command.parser.options) == 1 - option = command.wrapped_command.parser.options[0] - assert option.key == "other_value" - assert option.names == ["--other-value"] - assert option.converters == [int] - assert option.default is tanjun.abc.NO_PASS - assert option.empty_value is tanjun.abc.NO_DEFAULT - assert option.is_multi is False - assert option.min_length is None - assert option.max_length is None - assert option.min_value is None - assert option.max_value is None - - -def test_when_annotated_handles_unions(): + assert len(command.wrapped_command.parser.arguments) == 1 + argument = command.wrapped_command.parser.arguments[0] + assert argument.key == "value" + assert argument.converters == [] + assert argument.default is tanjun.abc.NO_PASS + assert argument.is_greedy is False + assert argument.is_multi is False + assert argument.min_length is None + assert argument.max_length is None + assert argument.min_value is None + assert argument.max_value is None + + assert len(command.wrapped_command.parser.options) == 1 + option = command.wrapped_command.parser.options[0] + assert option.key == "other_value" + assert option.names == ["--other-value"] + assert option.converters == [int] + assert option.default is tanjun.abc.NO_PASS + assert option.empty_value is tanjun.abc.NO_DEFAULT + assert option.is_multi is False + assert option.min_length is None + assert option.max_length is None + assert option.min_value is None + assert option.max_value is None + + +def test_when_annotated_handles_typing_unions(): @annotations.with_annotated_args(follow_wrapped=True) @tanjun.as_slash_command("name", "description") @tanjun.as_message_command("name") @@ -4996,78 +4992,76 @@ async def command( assert option.max_value is None -if sys.version_info >= (3, 10): +def test_when_annotated_handles_3_10_unions(): + @annotations.with_annotated_args(follow_wrapped=True) + @tanjun.as_slash_command("name", "description") + @tanjun.as_message_command("name") + async def command( + ctx: tanjun.abc.Context, + *, + value: typing.Annotated[annotations.Str | bool, annotations.Positional(), "nyaa"] = False, + other_value: typing.Annotated[annotations.Int | None, "meow"] = None, + ) -> None: + raise NotImplementedError - def test_when_annotated_handles_3_10_unions(): - @annotations.with_annotated_args(follow_wrapped=True) - @tanjun.as_slash_command("name", "description") - @tanjun.as_message_command("name") - async def command( - ctx: tanjun.abc.Context, - *, - value: typing.Annotated[annotations.Str | bool, annotations.Positional(), "nyaa"] = False, - other_value: typing.Annotated[annotations.Int | None, "meow"] = None, - ) -> None: - raise NotImplementedError - - assert command.build().options == [ - hikari.CommandOption(type=hikari.OptionType.STRING, name="value", description="nyaa", is_required=False), - hikari.CommandOption( - type=hikari.OptionType.INTEGER, - name="other_value", - description="meow", - is_required=False, - min_value=None, - max_value=None, - ), - ] + assert command.build().options == [ + hikari.CommandOption(type=hikari.OptionType.STRING, name="value", description="nyaa", is_required=False), + hikari.CommandOption( + type=hikari.OptionType.INTEGER, + name="other_value", + description="meow", + is_required=False, + min_value=None, + max_value=None, + ), + ] - assert len(command._tracked_options) == 2 - tracked_option = command._tracked_options["value"] - assert tracked_option.converters == [] - assert tracked_option.default is tanjun.abc.NO_PASS - assert tracked_option.is_always_float is False - assert tracked_option.is_only_member is False - assert tracked_option.key == "value" - assert tracked_option.name == "value" - assert tracked_option.type is hikari.OptionType.STRING - - tracked_option = command._tracked_options["other_value"] - assert tracked_option.converters == [] - assert tracked_option.default is tanjun.abc.NO_PASS - assert tracked_option.is_always_float is False - assert tracked_option.is_only_member is False - assert tracked_option.key == "other_value" - assert tracked_option.name == "other_value" - assert tracked_option.type is hikari.OptionType.INTEGER - - assert isinstance(command.wrapped_command, tanjun.MessageCommand) - assert isinstance(command.wrapped_command.parser, tanjun.ShlexParser) - - assert len(command.wrapped_command.parser.arguments) == 1 - argument = command.wrapped_command.parser.arguments[0] - assert argument.key == "value" - assert argument.converters == [] - assert argument.default is tanjun.abc.NO_PASS - assert argument.is_greedy is False - assert argument.is_multi is False - assert argument.min_length is None - assert argument.max_length is None - assert argument.min_value is None - assert argument.max_value is None - - assert len(command.wrapped_command.parser.options) == 1 - option = command.wrapped_command.parser.options[0] - assert option.key == "other_value" - assert option.names == ["--other-value"] - assert option.converters == [int] - assert option.default is tanjun.abc.NO_PASS - assert option.empty_value is tanjun.abc.NO_DEFAULT - assert option.is_multi is False - assert option.min_length is None - assert option.max_length is None - assert option.min_value is None - assert option.max_value is None + assert len(command._tracked_options) == 2 + tracked_option = command._tracked_options["value"] + assert tracked_option.converters == [] + assert tracked_option.default is tanjun.abc.NO_PASS + assert tracked_option.is_always_float is False + assert tracked_option.is_only_member is False + assert tracked_option.key == "value" + assert tracked_option.name == "value" + assert tracked_option.type is hikari.OptionType.STRING + + tracked_option = command._tracked_options["other_value"] + assert tracked_option.converters == [] + assert tracked_option.default is tanjun.abc.NO_PASS + assert tracked_option.is_always_float is False + assert tracked_option.is_only_member is False + assert tracked_option.key == "other_value" + assert tracked_option.name == "other_value" + assert tracked_option.type is hikari.OptionType.INTEGER + + assert isinstance(command.wrapped_command, tanjun.MessageCommand) + assert isinstance(command.wrapped_command.parser, tanjun.ShlexParser) + + assert len(command.wrapped_command.parser.arguments) == 1 + argument = command.wrapped_command.parser.arguments[0] + assert argument.key == "value" + assert argument.converters == [] + assert argument.default is tanjun.abc.NO_PASS + assert argument.is_greedy is False + assert argument.is_multi is False + assert argument.min_length is None + assert argument.max_length is None + assert argument.min_value is None + assert argument.max_value is None + + assert len(command.wrapped_command.parser.options) == 1 + option = command.wrapped_command.parser.options[0] + assert option.key == "other_value" + assert option.names == ["--other-value"] + assert option.converters == [int] + assert option.default is tanjun.abc.NO_PASS + assert option.empty_value is tanjun.abc.NO_DEFAULT + assert option.is_multi is False + assert option.min_length is None + assert option.max_length is None + assert option.min_value is None + assert option.max_value is None def test_parse_annotated_args_with_descriptions_argument(): @@ -6183,7 +6177,7 @@ async def command( with pytest.raises( RuntimeError, match=re.escape( - "Conflicting option types of typing.Union[hikari.users.User, hikari.guilds.Role] and " + "Conflicting option types of hikari.users.User | hikari.guilds.Role and " " found for 'ghost' parameter" ), ): @@ -6767,7 +6761,7 @@ class TypedDict(typing.TypedDict): @annotations.with_annotated_args(follow_wrapped=True) @tanjun.as_slash_command("a", "b") @tanjun.as_message_command("x", "3") - async def command(ctx: tanjun.abc.Context, **kwargs: typing_extensions.Unpack[TypedDict]) -> None: + async def command(ctx: tanjun.abc.Context, **kwargs: typing.Unpack[TypedDict]) -> None: raise NotImplementedError assert command.build().options == [ @@ -6822,11 +6816,11 @@ async def command(ctx: tanjun.abc.Context, **kwargs: typing_extensions.Unpack[Ty def test_with_unpacked_other_syntax_typed_dict(): - TypedDict = typing_extensions.TypedDict( # noqa: N806 + TypedDict = typing.TypedDict( # noqa: N806 "TypedDict", { - "baz": typing_extensions.NotRequired[typing.Annotated[annotations.Float, "eep"]], - "ban": typing_extensions.Required[typing.Annotated[annotations.Color, "beep"]], + "baz": typing.NotRequired[typing.Annotated[annotations.Float, "eep"]], + "ban": typing.Required[typing.Annotated[annotations.Color, "beep"]], "pickle": typing.Literal["Candy"], "nyaa": typing.Annotated[annotations.Bool, "meow"], }, @@ -6835,7 +6829,7 @@ def test_with_unpacked_other_syntax_typed_dict(): @annotations.with_annotated_args(follow_wrapped=True) @tanjun.as_slash_command("a", "b") @tanjun.as_message_command("x", "3") - async def command(ctx: tanjun.abc.Context, **kwargs: typing_extensions.Unpack[TypedDict]) -> None: + async def command(ctx: tanjun.abc.Context, **kwargs: typing.Unpack[TypedDict]) -> None: raise NotImplementedError assert command.build().options == [ @@ -6913,13 +6907,13 @@ async def command(ctx: tanjun.abc.Context, **kwargs: typing_extensions.Unpack[Ty def test_with_empty_unpacked_typed_dict(): - class TypedDict(typing_extensions.TypedDict): + class TypedDict(typing.TypedDict): pickle: str @annotations.with_annotated_args(follow_wrapped=True) @tanjun.as_slash_command("a", "b") @tanjun.as_message_command("x", "3") - async def command(ctx: tanjun.abc.Context, **kwargs: typing_extensions.Unpack[TypedDict]) -> None: + async def command(ctx: tanjun.abc.Context, **kwargs: typing.Unpack[TypedDict]) -> None: raise NotImplementedError assert command.build().options == [] @@ -6931,16 +6925,16 @@ async def command(ctx: tanjun.abc.Context, **kwargs: typing_extensions.Unpack[Ty def test_with_empty_unpacked_typed_dict_where_total_is_false(): - class TypedDict(typing_extensions.TypedDict, total=False): + class TypedDict(typing.TypedDict, total=False): me: typing.Annotated[annotations.Role, "c"] - too: typing_extensions.Required[typing.Annotated[annotations.Bool, "b"]] + too: typing.Required[typing.Annotated[annotations.Bool, "b"]] nope: str three: typing.Annotated[annotations.Str, "a"] @annotations.with_annotated_args(follow_wrapped=True) @tanjun.as_slash_command("a", "b") @tanjun.as_message_command("x", "3") - async def command(ctx: tanjun.abc.Context, **kwargs: typing_extensions.Unpack[TypedDict]) -> None: + async def command(ctx: tanjun.abc.Context, **kwargs: typing.Unpack[TypedDict]) -> None: raise NotImplementedError assert command.build().options == [ @@ -7019,17 +7013,15 @@ async def command(ctx: tanjun.abc.Context, **kwargs: typing_extensions.Unpack[Ty def test_with_unpacked_typed_dict_and_other_args(): - class TypedDict(typing_extensions.TypedDict): - other: typing_extensions.NotRequired[typing.Annotated[annotations.Int, "bat"]] + class TypedDict(typing.TypedDict): + other: typing.NotRequired[typing.Annotated[annotations.Int, "bat"]] value: typing.Annotated[annotations.User, "meow"] @annotations.with_annotated_args(follow_wrapped=True) @tanjun.as_slash_command("a", "b") @tanjun.as_message_command("x", "3") async def command( - ctx: tanjun.abc.Context, - blam: typing.Annotated[annotations.Bool, "sleep"], - **kwargs: typing_extensions.Unpack[TypedDict], + ctx: tanjun.abc.Context, blam: typing.Annotated[annotations.Bool, "sleep"], **kwargs: typing.Unpack[TypedDict] ) -> None: raise NotImplementedError @@ -7108,13 +7100,13 @@ async def command( def test_with_unpacked_typed_dict_and_attachment(): - class TypedDict(typing_extensions.TypedDict): + class TypedDict(typing.TypedDict): field: typing.Annotated[annotations.Attachment, "meow"] - other: typing_extensions.NotRequired[typing.Annotated[annotations.Attachment, "nyaa"]] + other: typing.NotRequired[typing.Annotated[annotations.Attachment, "nyaa"]] @annotations.with_annotated_args(follow_wrapped=True) @tanjun.as_slash_command("a", "b") - async def command(ctx: tanjun.abc.Context, **kwargs: typing_extensions.Unpack[TypedDict]) -> None: + async def command(ctx: tanjun.abc.Context, **kwargs: typing.Unpack[TypedDict]) -> None: raise NotImplementedError assert command.build().options == [ @@ -7143,14 +7135,14 @@ async def command(ctx: tanjun.abc.Context, **kwargs: typing_extensions.Unpack[Ty def test_with_unpacked_typed_dict_and_bool(): - class TypedDict(typing_extensions.TypedDict): + class TypedDict(typing.TypedDict): fi: typing.Annotated[annotations.Bool, "nn"] - to: typing_extensions.NotRequired[typing.Annotated[annotations.Bool, "xn"]] + to: typing.NotRequired[typing.Annotated[annotations.Bool, "xn"]] @annotations.with_annotated_args(follow_wrapped=True) @tanjun.as_slash_command("a", "b") @tanjun.as_message_command("x", "3") - async def command(ctx: tanjun.abc.Context, **kwargs: typing_extensions.Unpack[TypedDict]) -> None: + async def command(ctx: tanjun.abc.Context, **kwargs: typing.Unpack[TypedDict]) -> None: raise NotImplementedError assert command.build().options == [ @@ -7207,14 +7199,14 @@ async def command(ctx: tanjun.abc.Context, **kwargs: typing_extensions.Unpack[Ty def test_with_unpacked_typed_dict_and_channel(): - class TypedDict(typing_extensions.TypedDict): + class TypedDict(typing.TypedDict): of: typing.Annotated[annotations.Channel, "maaaa"] - oo: typing_extensions.NotRequired[typing.Annotated[annotations.Channel, "xat"]] + oo: typing.NotRequired[typing.Annotated[annotations.Channel, "xat"]] @annotations.with_annotated_args(follow_wrapped=True) @tanjun.as_slash_command("a", "b") @tanjun.as_message_command("x", "3") - async def command(ctx: tanjun.abc.Context, **kwargs: typing_extensions.Unpack[TypedDict]) -> None: + async def command(ctx: tanjun.abc.Context, **kwargs: typing.Unpack[TypedDict]) -> None: raise NotImplementedError assert command.build().options == [ @@ -7273,16 +7265,14 @@ async def command(ctx: tanjun.abc.Context, **kwargs: typing_extensions.Unpack[Ty def test_with_unpacked_typed_dict_and_choices(): - class TypedDict(typing_extensions.TypedDict): + class TypedDict(typing.TypedDict): of: typing.Annotated[annotations.Str, annotations.Choices({"hi": "meow", "blam": "xd"}), "maaaa"] - oo: typing_extensions.NotRequired[ - typing.Annotated[annotations.Int, annotations.Choices({"m": 1, "ddd": 420}), "xat"] - ] + oo: typing.NotRequired[typing.Annotated[annotations.Int, annotations.Choices({"m": 1, "ddd": 420}), "xat"]] @annotations.with_annotated_args(follow_wrapped=True) @tanjun.as_slash_command("a", "b") @tanjun.as_message_command("x", "3") - async def command(ctx: tanjun.abc.Context, **kwargs: typing_extensions.Unpack[TypedDict]) -> None: + async def command(ctx: tanjun.abc.Context, **kwargs: typing.Unpack[TypedDict]) -> None: raise NotImplementedError assert command.build().options == [ @@ -7351,14 +7341,14 @@ async def command(ctx: tanjun.abc.Context, **kwargs: typing_extensions.Unpack[Ty def test_with_unpacked_typed_dict_and_color(): - class TypedDict(typing_extensions.TypedDict): + class TypedDict(typing.TypedDict): of: typing.Annotated[annotations.Color, "maaaa"] - oo: typing_extensions.NotRequired[typing.Annotated[annotations.Color, "xat"]] + oo: typing.NotRequired[typing.Annotated[annotations.Color, "xat"]] @annotations.with_annotated_args(follow_wrapped=True) @tanjun.as_slash_command("a", "b") @tanjun.as_message_command("x", "3") - async def command(ctx: tanjun.abc.Context, **kwargs: typing_extensions.Unpack[TypedDict]) -> None: + async def command(ctx: tanjun.abc.Context, **kwargs: typing.Unpack[TypedDict]) -> None: raise NotImplementedError assert command.build().options == [ @@ -7418,14 +7408,14 @@ def test_with_unpacked_typed_dict_and_converted(): mock_callback_1 = mock.Mock() mock_callback_2 = mock.Mock() - class TypedDict(typing_extensions.TypedDict): + class TypedDict(typing.TypedDict): of: typing.Annotated[typing.Any, annotations.Converted(mock_callback_1), "maaaa"] - oo: typing_extensions.NotRequired[typing.Annotated[typing.Any, annotations.Converted(mock_callback_2), "xat"]] + oo: typing.NotRequired[typing.Annotated[typing.Any, annotations.Converted(mock_callback_2), "xat"]] @annotations.with_annotated_args(follow_wrapped=True) @tanjun.as_slash_command("a", "b") @tanjun.as_message_command("x", "3") - async def command(ctx: tanjun.abc.Context, **kwargs: typing_extensions.Unpack[TypedDict]) -> None: + async def command(ctx: tanjun.abc.Context, **kwargs: typing.Unpack[TypedDict]) -> None: raise NotImplementedError assert command.build().options == [ @@ -7482,14 +7472,14 @@ async def command(ctx: tanjun.abc.Context, **kwargs: typing_extensions.Unpack[Ty def test_with_unpacked_typed_dict_and_datetime(): - class TypedDict(typing_extensions.TypedDict): + class TypedDict(typing.TypedDict): of: typing.Annotated[annotations.Datetime, "maaaa"] - oo: typing_extensions.NotRequired[typing.Annotated[annotations.Datetime, "xat"]] + oo: typing.NotRequired[typing.Annotated[annotations.Datetime, "xat"]] @annotations.with_annotated_args(follow_wrapped=True) @tanjun.as_slash_command("a", "b") @tanjun.as_message_command("x", "3") - async def command(ctx: tanjun.abc.Context, **kwargs: typing_extensions.Unpack[TypedDict]) -> None: + async def command(ctx: tanjun.abc.Context, **kwargs: typing.Unpack[TypedDict]) -> None: raise NotImplementedError assert command.build().options == [ @@ -7546,14 +7536,14 @@ async def command(ctx: tanjun.abc.Context, **kwargs: typing_extensions.Unpack[Ty def test_with_unpacked_typed_dict_and_default(): - class TypedDict(typing_extensions.TypedDict): + class TypedDict(typing.TypedDict): of: typing.Annotated[annotations.Int, annotations.Default(0), "maaaa"] - oo: typing_extensions.NotRequired[typing.Annotated[annotations.Float, annotations.Default(0.1), "xat"]] + oo: typing.NotRequired[typing.Annotated[annotations.Float, annotations.Default(0.1), "xat"]] @annotations.with_annotated_args(follow_wrapped=True) @tanjun.as_slash_command("a", "b") @tanjun.as_message_command("x", "3") - async def command(ctx: tanjun.abc.Context, **kwargs: typing_extensions.Unpack[TypedDict]) -> None: + async def command(ctx: tanjun.abc.Context, **kwargs: typing.Unpack[TypedDict]) -> None: raise NotImplementedError assert command.build().options == [ @@ -7610,15 +7600,15 @@ async def command(ctx: tanjun.abc.Context, **kwargs: typing_extensions.Unpack[Ty def test_with_unpacked_typed_dict_and_flag(): - class TypedDict(typing_extensions.TypedDict): - of: typing_extensions.NotRequired[ + class TypedDict(typing.TypedDict): + of: typing.NotRequired[ typing.Annotated[annotations.Int, annotations.Flag(aliases=["-o"], empty_value="aaaa"), "maaaa"] ] @annotations.with_annotated_args(follow_wrapped=True) @tanjun.as_slash_command("a", "b") @tanjun.as_message_command("x", "3") - async def command(ctx: tanjun.abc.Context, **kwargs: typing_extensions.Unpack[TypedDict]) -> None: + async def command(ctx: tanjun.abc.Context, **kwargs: typing.Unpack[TypedDict]) -> None: raise NotImplementedError assert command.build().options == [ @@ -7655,14 +7645,14 @@ async def command(ctx: tanjun.abc.Context, **kwargs: typing_extensions.Unpack[Ty def test_with_unpacked_typed_dict_and_float(): - class TypedDict(typing_extensions.TypedDict): + class TypedDict(typing.TypedDict): of: typing.Annotated[annotations.Float, "maaaa"] - oo: typing_extensions.NotRequired[typing.Annotated[annotations.Float, "xat"]] + oo: typing.NotRequired[typing.Annotated[annotations.Float, "xat"]] @annotations.with_annotated_args(follow_wrapped=True) @tanjun.as_slash_command("a", "b") @tanjun.as_message_command("x", "3") - async def command(ctx: tanjun.abc.Context, **kwargs: typing_extensions.Unpack[TypedDict]) -> None: + async def command(ctx: tanjun.abc.Context, **kwargs: typing.Unpack[TypedDict]) -> None: raise NotImplementedError assert command.build().options == [ @@ -7719,13 +7709,13 @@ async def command(ctx: tanjun.abc.Context, **kwargs: typing_extensions.Unpack[Ty def test_with_unpacked_typed_dict_and_greedy(): - class TypedDict(typing_extensions.TypedDict): + class TypedDict(typing.TypedDict): of: typing.Annotated[annotations.Str, annotations.Greedy(), "maaaa"] @annotations.with_annotated_args(follow_wrapped=True) @tanjun.as_slash_command("a", "b") @tanjun.as_message_command("x", "3") - async def command(ctx: tanjun.abc.Context, **kwargs: typing_extensions.Unpack[TypedDict]) -> None: + async def command(ctx: tanjun.abc.Context, **kwargs: typing.Unpack[TypedDict]) -> None: raise NotImplementedError assert command.build().options == [ @@ -7761,14 +7751,14 @@ async def command(ctx: tanjun.abc.Context, **kwargs: typing_extensions.Unpack[Ty def test_with_unpacked_typed_dict_and_int(): - class TypedDict(typing_extensions.TypedDict): + class TypedDict(typing.TypedDict): of: typing.Annotated[annotations.Int, "maaaa"] - oo: typing_extensions.NotRequired[typing.Annotated[annotations.Int, "xat"]] + oo: typing.NotRequired[typing.Annotated[annotations.Int, "xat"]] @annotations.with_annotated_args(follow_wrapped=True) @tanjun.as_slash_command("a", "b") @tanjun.as_message_command("x", "3") - async def command(ctx: tanjun.abc.Context, **kwargs: typing_extensions.Unpack[TypedDict]) -> None: + async def command(ctx: tanjun.abc.Context, **kwargs: typing.Unpack[TypedDict]) -> None: raise NotImplementedError assert command.build().options == [ @@ -7825,13 +7815,13 @@ async def command(ctx: tanjun.abc.Context, **kwargs: typing_extensions.Unpack[Ty def test_with_unpacked_typed_dict_and_interaction_channel(): - class TypedDict(typing_extensions.TypedDict): + class TypedDict(typing.TypedDict): of: typing.Annotated[annotations.InteractionChannel, "maaaa"] - oo: typing_extensions.NotRequired[typing.Annotated[annotations.InteractionChannel, "xat"]] + oo: typing.NotRequired[typing.Annotated[annotations.InteractionChannel, "xat"]] @annotations.with_annotated_args(follow_wrapped=True) @tanjun.as_slash_command("a", "b") - async def command(ctx: tanjun.abc.Context, **kwargs: typing_extensions.Unpack[TypedDict]) -> None: + async def command(ctx: tanjun.abc.Context, **kwargs: typing.Unpack[TypedDict]) -> None: raise NotImplementedError assert command.build().options == [ @@ -7860,13 +7850,13 @@ async def command(ctx: tanjun.abc.Context, **kwargs: typing_extensions.Unpack[Ty def test_with_unpacked_typed_dict_and_interaction_member(): - class TypedDict(typing_extensions.TypedDict): + class TypedDict(typing.TypedDict): of: typing.Annotated[annotations.InteractionMember, "maaaa"] - oo: typing_extensions.NotRequired[typing.Annotated[annotations.InteractionMember, "xat"]] + oo: typing.NotRequired[typing.Annotated[annotations.InteractionMember, "xat"]] @annotations.with_annotated_args(follow_wrapped=True) @tanjun.as_slash_command("a", "b") - async def command(ctx: tanjun.abc.Context, **kwargs: typing_extensions.Unpack[TypedDict]) -> None: + async def command(ctx: tanjun.abc.Context, **kwargs: typing.Unpack[TypedDict]) -> None: raise NotImplementedError assert command.build().options == [ @@ -7895,14 +7885,14 @@ async def command(ctx: tanjun.abc.Context, **kwargs: typing_extensions.Unpack[Ty def test_with_unpacked_typed_dict_and_length(): - class TypedDict(typing_extensions.TypedDict): + class TypedDict(typing.TypedDict): of: typing.Annotated[annotations.Str, annotations.Length(232), "maaaa"] - oo: typing_extensions.NotRequired[typing.Annotated[annotations.Str, annotations.Length(4, 128), "xat"]] + oo: typing.NotRequired[typing.Annotated[annotations.Str, annotations.Length(4, 128), "xat"]] @annotations.with_annotated_args(follow_wrapped=True) @tanjun.as_slash_command("a", "b") @tanjun.as_message_command("x", "3") - async def command(ctx: tanjun.abc.Context, **kwargs: typing_extensions.Unpack[TypedDict]) -> None: + async def command(ctx: tanjun.abc.Context, **kwargs: typing.Unpack[TypedDict]) -> None: raise NotImplementedError assert command.build().options == [ @@ -7968,14 +7958,14 @@ async def command(ctx: tanjun.abc.Context, **kwargs: typing_extensions.Unpack[Ty def test_with_unpacked_typed_dict_and_max(): - class TypedDict(typing_extensions.TypedDict): + class TypedDict(typing.TypedDict): of: typing.Annotated[annotations.Int, annotations.Max(453), "maaaa"] - oo: typing_extensions.NotRequired[typing.Annotated[annotations.Float, annotations.Max(69.420), "xat"]] + oo: typing.NotRequired[typing.Annotated[annotations.Float, annotations.Max(69.420), "xat"]] @annotations.with_annotated_args(follow_wrapped=True) @tanjun.as_slash_command("a", "b") @tanjun.as_message_command("x", "3") - async def command(ctx: tanjun.abc.Context, **kwargs: typing_extensions.Unpack[TypedDict]) -> None: + async def command(ctx: tanjun.abc.Context, **kwargs: typing.Unpack[TypedDict]) -> None: raise NotImplementedError assert command.build().options == [ @@ -8036,14 +8026,14 @@ async def command(ctx: tanjun.abc.Context, **kwargs: typing_extensions.Unpack[Ty def test_with_unpacked_typed_dict_and_member(): - class TypedDict(typing_extensions.TypedDict): + class TypedDict(typing.TypedDict): of: typing.Annotated[annotations.Member, "maaaa"] - oo: typing_extensions.NotRequired[typing.Annotated[annotations.Member, "xat"]] + oo: typing.NotRequired[typing.Annotated[annotations.Member, "xat"]] @annotations.with_annotated_args(follow_wrapped=True) @tanjun.as_slash_command("a", "b") @tanjun.as_message_command("x", "3") - async def command(ctx: tanjun.abc.Context, **kwargs: typing_extensions.Unpack[TypedDict]) -> None: + async def command(ctx: tanjun.abc.Context, **kwargs: typing.Unpack[TypedDict]) -> None: raise NotImplementedError assert command.build().options == [ @@ -8100,14 +8090,14 @@ async def command(ctx: tanjun.abc.Context, **kwargs: typing_extensions.Unpack[Ty def test_with_unpacked_typed_dict_and_mentionable(): - class TypedDict(typing_extensions.TypedDict): + class TypedDict(typing.TypedDict): of: typing.Annotated[annotations.Mentionable, "maaaa"] - oo: typing_extensions.NotRequired[typing.Annotated[annotations.Mentionable, "xat"]] + oo: typing.NotRequired[typing.Annotated[annotations.Mentionable, "xat"]] @annotations.with_annotated_args(follow_wrapped=True) @tanjun.as_slash_command("a", "b") @tanjun.as_message_command("x", "3") - async def command(ctx: tanjun.abc.Context, **kwargs: typing_extensions.Unpack[TypedDict]) -> None: + async def command(ctx: tanjun.abc.Context, **kwargs: typing.Unpack[TypedDict]) -> None: raise NotImplementedError assert command.build().options == [ @@ -8164,14 +8154,14 @@ async def command(ctx: tanjun.abc.Context, **kwargs: typing_extensions.Unpack[Ty def test_with_unpacked_typed_dict_and_min(): - class TypedDict(typing_extensions.TypedDict): + class TypedDict(typing.TypedDict): of: typing.Annotated[annotations.Float, annotations.Min(3.2), "maaaa"] - oo: typing_extensions.NotRequired[typing.Annotated[annotations.Int, annotations.Min(32), "xat"]] + oo: typing.NotRequired[typing.Annotated[annotations.Int, annotations.Min(32), "xat"]] @annotations.with_annotated_args(follow_wrapped=True) @tanjun.as_slash_command("a", "b") @tanjun.as_message_command("x", "3") - async def command(ctx: tanjun.abc.Context, **kwargs: typing_extensions.Unpack[TypedDict]) -> None: + async def command(ctx: tanjun.abc.Context, **kwargs: typing.Unpack[TypedDict]) -> None: raise NotImplementedError assert command.build().options == [ @@ -8232,14 +8222,14 @@ async def command(ctx: tanjun.abc.Context, **kwargs: typing_extensions.Unpack[Ty def test_with_unpacked_typed_dict_and_name(): - class TypedDict(typing_extensions.TypedDict): + class TypedDict(typing.TypedDict): of: typing.Annotated[annotations.Float, annotations.Name("hi"), "maaaa"] - oo: typing_extensions.NotRequired[typing.Annotated[annotations.User, annotations.Name("nye"), "xat"]] + oo: typing.NotRequired[typing.Annotated[annotations.User, annotations.Name("nye"), "xat"]] @annotations.with_annotated_args(follow_wrapped=True) @tanjun.as_slash_command("a", "b") @tanjun.as_message_command("x", "3") - async def command(ctx: tanjun.abc.Context, **kwargs: typing_extensions.Unpack[TypedDict]) -> None: + async def command(ctx: tanjun.abc.Context, **kwargs: typing.Unpack[TypedDict]) -> None: raise NotImplementedError assert command.build().options == [ @@ -8296,13 +8286,13 @@ async def command(ctx: tanjun.abc.Context, **kwargs: typing_extensions.Unpack[Ty def test_with_unpacked_typed_dict_and_positional(): - class TypedDict(typing_extensions.TypedDict): + class TypedDict(typing.TypedDict): of: typing.Annotated[annotations.Int, annotations.Positional(), "maaaa"] - oo: typing_extensions.NotRequired[typing.Annotated[annotations.Str, annotations.Positional(), "xat"]] + oo: typing.NotRequired[typing.Annotated[annotations.Str, annotations.Positional(), "xat"]] @annotations.with_annotated_args(follow_wrapped=True) @tanjun.as_message_command("x", "3") - async def command(ctx: tanjun.abc.Context, **kwargs: typing_extensions.Unpack[TypedDict]) -> None: + async def command(ctx: tanjun.abc.Context, **kwargs: typing.Unpack[TypedDict]) -> None: raise NotImplementedError assert isinstance(command.parser, tanjun.ShlexParser) @@ -8334,14 +8324,14 @@ async def command(ctx: tanjun.abc.Context, **kwargs: typing_extensions.Unpack[Ty def test_with_unpacked_typed_dict_and_ranged(): - class TypedDict(typing_extensions.TypedDict): + class TypedDict(typing.TypedDict): of: typing.Annotated[annotations.Int, annotations.Ranged(4, 64), "maaaa"] - oo: typing_extensions.NotRequired[typing.Annotated[annotations.Float, annotations.Ranged(12.21, 54.34), "xat"]] + oo: typing.NotRequired[typing.Annotated[annotations.Float, annotations.Ranged(12.21, 54.34), "xat"]] @annotations.with_annotated_args(follow_wrapped=True) @tanjun.as_slash_command("a", "b") @tanjun.as_message_command("x", "3") - async def command(ctx: tanjun.abc.Context, **kwargs: typing_extensions.Unpack[TypedDict]) -> None: + async def command(ctx: tanjun.abc.Context, **kwargs: typing.Unpack[TypedDict]) -> None: raise NotImplementedError assert command.build().options == [ @@ -8407,14 +8397,14 @@ async def command(ctx: tanjun.abc.Context, **kwargs: typing_extensions.Unpack[Ty def test_with_unpacked_typed_dict_and_role(): - class TypedDict(typing_extensions.TypedDict): + class TypedDict(typing.TypedDict): of: typing.Annotated[annotations.Role, "maaaa"] - oo: typing_extensions.NotRequired[typing.Annotated[annotations.Role, "xat"]] + oo: typing.NotRequired[typing.Annotated[annotations.Role, "xat"]] @annotations.with_annotated_args(follow_wrapped=True) @tanjun.as_slash_command("a", "b") @tanjun.as_message_command("x", "3") - async def command(ctx: tanjun.abc.Context, **kwargs: typing_extensions.Unpack[TypedDict]) -> None: + async def command(ctx: tanjun.abc.Context, **kwargs: typing.Unpack[TypedDict]) -> None: raise NotImplementedError assert command.build().options == [ @@ -8471,14 +8461,14 @@ async def command(ctx: tanjun.abc.Context, **kwargs: typing_extensions.Unpack[Ty def test_with_unpacked_typed_dict_and_snowflake(): - class TypedDict(typing_extensions.TypedDict): + class TypedDict(typing.TypedDict): of: typing.Annotated[annotations.Snowflake, "maaaa"] - oo: typing_extensions.NotRequired[typing.Annotated[annotations.Snowflake, "xat"]] + oo: typing.NotRequired[typing.Annotated[annotations.Snowflake, "xat"]] @annotations.with_annotated_args(follow_wrapped=True) @tanjun.as_slash_command("a", "b") @tanjun.as_message_command("x", "3") - async def command(ctx: tanjun.abc.Context, **kwargs: typing_extensions.Unpack[TypedDict]) -> None: + async def command(ctx: tanjun.abc.Context, **kwargs: typing.Unpack[TypedDict]) -> None: raise NotImplementedError assert command.build().options == [ @@ -8535,13 +8525,13 @@ async def command(ctx: tanjun.abc.Context, **kwargs: typing_extensions.Unpack[Ty def test_with_unpacked_typed_dict_and_snowflake_or(): - class TypedDict(typing_extensions.TypedDict): + class TypedDict(typing.TypedDict): of: typing.Annotated[ typing.Union[annotations.Role, hikari.Snowflake], annotations.SnowflakeOr(parse_id=tanjun.conversion.parse_role_id), "maaaa", ] - oo: typing_extensions.NotRequired[ + oo: typing.NotRequired[ typing.Annotated[ typing.Union[annotations.Member, hikari.Snowflake], annotations.SnowflakeOr(parse_id=tanjun.conversion.parse_user_id), @@ -8552,7 +8542,7 @@ class TypedDict(typing_extensions.TypedDict): @annotations.with_annotated_args(follow_wrapped=True) @tanjun.as_slash_command("a", "b") @tanjun.as_message_command("x", "3") - async def command(ctx: tanjun.abc.Context, **kwargs: typing_extensions.Unpack[TypedDict]) -> None: + async def command(ctx: tanjun.abc.Context, **kwargs: typing.Unpack[TypedDict]) -> None: raise NotImplementedError assert command.build().options == [ @@ -8609,14 +8599,14 @@ async def command(ctx: tanjun.abc.Context, **kwargs: typing_extensions.Unpack[Ty def test_with_unpacked_typed_dict_and_str(): - class TypedDict(typing_extensions.TypedDict): + class TypedDict(typing.TypedDict): of: typing.Annotated[annotations.Str, "maaaa"] - oo: typing_extensions.NotRequired[typing.Annotated[annotations.Str, "xat"]] + oo: typing.NotRequired[typing.Annotated[annotations.Str, "xat"]] @annotations.with_annotated_args(follow_wrapped=True) @tanjun.as_slash_command("a", "b") @tanjun.as_message_command("x", "3") - async def command(ctx: tanjun.abc.Context, **kwargs: typing_extensions.Unpack[TypedDict]) -> None: + async def command(ctx: tanjun.abc.Context, **kwargs: typing.Unpack[TypedDict]) -> None: raise NotImplementedError assert command.build().options == [ @@ -8673,18 +8663,18 @@ async def command(ctx: tanjun.abc.Context, **kwargs: typing_extensions.Unpack[Ty def test_with_unpacked_typed_dict_and_these_channels(): - class TypedDict(typing_extensions.TypedDict): + class TypedDict(typing.TypedDict): of: typing.Annotated[ annotations.Channel, annotations.TheseChannels(hikari.ChannelType.DM, hikari.GuildThreadChannel), "maaaa" ] - oo: typing_extensions.NotRequired[ + oo: typing.NotRequired[ typing.Annotated[annotations.Channel, annotations.TheseChannels(hikari.GuildTextChannel), "xat"] ] @annotations.with_annotated_args(follow_wrapped=True) @tanjun.as_slash_command("a", "b") @tanjun.as_message_command("x", "3") - async def command(ctx: tanjun.abc.Context, **kwargs: typing_extensions.Unpack[TypedDict]) -> None: + async def command(ctx: tanjun.abc.Context, **kwargs: typing.Unpack[TypedDict]) -> None: raise NotImplementedError assert command.build().options == [ @@ -8767,14 +8757,14 @@ async def command(ctx: tanjun.abc.Context, **kwargs: typing_extensions.Unpack[Ty def test_with_unpacked_typed_dict_and_user(): - class TypedDict(typing_extensions.TypedDict): + class TypedDict(typing.TypedDict): of: typing.Annotated[annotations.User, "maaaa"] - oo: typing_extensions.NotRequired[typing.Annotated[annotations.User, "xat"]] + oo: typing.NotRequired[typing.Annotated[annotations.User, "xat"]] @annotations.with_annotated_args(follow_wrapped=True) @tanjun.as_slash_command("a", "b") @tanjun.as_message_command("x", "3") - async def command(ctx: tanjun.abc.Context, **kwargs: typing_extensions.Unpack[TypedDict]) -> None: + async def command(ctx: tanjun.abc.Context, **kwargs: typing.Unpack[TypedDict]) -> None: raise NotImplementedError assert command.build().options == [ @@ -8833,12 +8823,12 @@ async def command(ctx: tanjun.abc.Context, **kwargs: typing_extensions.Unpack[Ty def test_ignores_non_typed_dict_class_in_kwargs_unpack(): class CustomClass: of: typing.Annotated[annotations.User, "maaaa"] # pyright: ignore[reportUninitializedInstanceVariable] - oo: typing_extensions.NotRequired[typing.Annotated[annotations.User, "xat"]] # type: ignore + oo: typing.NotRequired[typing.Annotated[annotations.User, "xat"]] # type: ignore @annotations.with_annotated_args(follow_wrapped=True) @tanjun.as_slash_command("a", "b") @tanjun.as_message_command("x", "3") - async def command(ctx: tanjun.abc.Context, **kwargs: typing_extensions.Unpack[CustomClass]) -> None: # type: ignore + async def command(ctx: tanjun.abc.Context, **kwargs: typing.Unpack[CustomClass]) -> None: # type: ignore raise NotImplementedError assert command.build().options == [] @@ -8849,9 +8839,9 @@ async def command(ctx: tanjun.abc.Context, **kwargs: typing_extensions.Unpack[Cu def test_ignores_non_unpack_kwargs(): - class TypedDict(typing_extensions.TypedDict): + class TypedDict(typing.TypedDict): meow: typing.Annotated[annotations.User, "maaaa"] - echo: typing_extensions.NotRequired[typing.Annotated[annotations.User, "xat"]] + echo: typing.NotRequired[typing.Annotated[annotations.User, "xat"]] @annotations.with_annotated_args(follow_wrapped=True) @tanjun.as_slash_command("a", "b") @@ -8867,14 +8857,14 @@ async def command(ctx: tanjun.abc.Context, **kwargs: TypedDict) -> None: def test_ignores_unpack_typed_dict_for_varargs(): - class TypedDict(typing_extensions.TypedDict): + class TypedDict(typing.TypedDict): meow: typing.Annotated[annotations.User, "maaaa"] - echo: typing_extensions.NotRequired[typing.Annotated[annotations.User, "xat"]] + echo: typing.NotRequired[typing.Annotated[annotations.User, "xat"]] @annotations.with_annotated_args(follow_wrapped=True) @tanjun.as_slash_command("a", "b") @tanjun.as_message_command("x", "3") - async def command(ctx: tanjun.abc.Context, *args: typing_extensions.Unpack[TypedDict]) -> None: # type: ignore + async def command(ctx: tanjun.abc.Context, *args: typing.Unpack[TypedDict]) -> None: # type: ignore raise NotImplementedError assert command.build().options == [] @@ -8885,14 +8875,14 @@ async def command(ctx: tanjun.abc.Context, *args: typing_extensions.Unpack[Typed def test_ignores_unpack_typed_dict_for_non_var_arg(): - class TypedDict(typing_extensions.TypedDict): + class TypedDict(typing.TypedDict): meow: typing.Annotated[annotations.User, "maaaa"] - echo: typing_extensions.NotRequired[typing.Annotated[annotations.User, "xat"]] + echo: typing.NotRequired[typing.Annotated[annotations.User, "xat"]] @annotations.with_annotated_args(follow_wrapped=True) @tanjun.as_slash_command("a", "b") @tanjun.as_message_command("x", "3") - async def command(ctx: tanjun.abc.Context, arg: typing_extensions.Unpack[TypedDict]) -> None: # type: ignore + async def command(ctx: tanjun.abc.Context, arg: typing.Unpack[TypedDict]) -> None: # type: ignore raise NotImplementedError assert command.build().options == [] diff --git a/tests/test_annotations_future_annotations.py b/tests/test_annotations_future_annotations.py index ac182b694..a06d8ab62 100644 --- a/tests/test_annotations_future_annotations.py +++ b/tests/test_annotations_future_annotations.py @@ -33,13 +33,12 @@ import enum import inspect import re -import sys import typing from collections import abc as collections +from unittest import mock import alluka import hikari -import mock import pytest import tanjun @@ -4606,7 +4605,7 @@ async def command( assert tracked_option.type is hikari.OptionType.USER -def test_when_annotated_not_top_level(): +def test_when_annotated_not_top_level_typing_union(): @annotations.with_annotated_args(follow_wrapped=True) @tanjun.as_slash_command("name", "description") @tanjun.as_message_command("name") @@ -4678,81 +4677,79 @@ async def command( assert option.max_value is None -if sys.version_info >= (3, 10): +def test_when_annotated_not_top_level_3_10_union(): + @annotations.with_annotated_args(follow_wrapped=True) + @tanjun.as_slash_command("name", "description") + @tanjun.as_message_command("name") + async def command( + ctx: tanjun.abc.Context, + *, + value: typing.Annotated[annotations.Str, annotations.Positional(), "nyaa"] | bool = False, + other_value: typing.Annotated[annotations.Int, "meow"] | None = None, + ) -> None: + raise NotImplementedError - def test_when_annotated_not_top_level_3_10_union(): - @annotations.with_annotated_args(follow_wrapped=True) - @tanjun.as_slash_command("name", "description") - @tanjun.as_message_command("name") - async def command( - ctx: tanjun.abc.Context, - *, - value: typing.Annotated[annotations.Str, annotations.Positional(), "nyaa"] | bool = False, - other_value: typing.Annotated[annotations.Int, "meow"] | None = None, - ) -> None: - raise NotImplementedError - - assert command.build().options == [ - hikari.CommandOption(type=hikari.OptionType.STRING, name="value", description="nyaa", is_required=False), - hikari.CommandOption( - type=hikari.OptionType.INTEGER, - name="other_value", - description="meow", - is_required=False, - min_value=None, - max_value=None, - ), - ] - - assert len(command._tracked_options) == 2 - tracked_option = command._tracked_options["value"] - assert tracked_option.converters == [] - assert tracked_option.default is tanjun.abc.NO_PASS - assert tracked_option.is_always_float is False - assert tracked_option.is_only_member is False - assert tracked_option.key == "value" - assert tracked_option.name == "value" - assert tracked_option.type is hikari.OptionType.STRING - - tracked_option = command._tracked_options["other_value"] - assert tracked_option.converters == [] - assert tracked_option.default is tanjun.abc.NO_PASS - assert tracked_option.is_always_float is False - assert tracked_option.is_only_member is False - assert tracked_option.key == "other_value" - assert tracked_option.name == "other_value" - assert tracked_option.type is hikari.OptionType.INTEGER - - assert isinstance(command.wrapped_command, tanjun.MessageCommand) - assert isinstance(command.wrapped_command.parser, tanjun.ShlexParser) - - assert len(command.wrapped_command.parser.arguments) == 1 - argument = command.wrapped_command.parser.arguments[0] - assert argument.key == "value" - assert argument.converters == [] - assert argument.default is tanjun.abc.NO_PASS - assert argument.is_greedy is False - assert argument.is_multi is False - assert argument.min_length is None - assert argument.max_length is None - assert argument.min_value is None - assert argument.max_value is None - - assert len(command.wrapped_command.parser.options) == 1 - option = command.wrapped_command.parser.options[0] - assert option.key == "other_value" - assert option.names == ["--other-value"] - assert option.converters == [int] - assert option.default is tanjun.abc.NO_PASS - assert option.empty_value is tanjun.abc.NO_DEFAULT - assert option.is_multi is False - assert option.min_length is None - assert option.max_length is None - assert option.min_value is None - assert option.max_value is None - - -def test_when_annotated_handles_unions(): + assert command.build().options == [ + hikari.CommandOption(type=hikari.OptionType.STRING, name="value", description="nyaa", is_required=False), + hikari.CommandOption( + type=hikari.OptionType.INTEGER, + name="other_value", + description="meow", + is_required=False, + min_value=None, + max_value=None, + ), + ] + + assert len(command._tracked_options) == 2 + tracked_option = command._tracked_options["value"] + assert tracked_option.converters == [] + assert tracked_option.default is tanjun.abc.NO_PASS + assert tracked_option.is_always_float is False + assert tracked_option.is_only_member is False + assert tracked_option.key == "value" + assert tracked_option.name == "value" + assert tracked_option.type is hikari.OptionType.STRING + + tracked_option = command._tracked_options["other_value"] + assert tracked_option.converters == [] + assert tracked_option.default is tanjun.abc.NO_PASS + assert tracked_option.is_always_float is False + assert tracked_option.is_only_member is False + assert tracked_option.key == "other_value" + assert tracked_option.name == "other_value" + assert tracked_option.type is hikari.OptionType.INTEGER + + assert isinstance(command.wrapped_command, tanjun.MessageCommand) + assert isinstance(command.wrapped_command.parser, tanjun.ShlexParser) + + assert len(command.wrapped_command.parser.arguments) == 1 + argument = command.wrapped_command.parser.arguments[0] + assert argument.key == "value" + assert argument.converters == [] + assert argument.default is tanjun.abc.NO_PASS + assert argument.is_greedy is False + assert argument.is_multi is False + assert argument.min_length is None + assert argument.max_length is None + assert argument.min_value is None + assert argument.max_value is None + + assert len(command.wrapped_command.parser.options) == 1 + option = command.wrapped_command.parser.options[0] + assert option.key == "other_value" + assert option.names == ["--other-value"] + assert option.converters == [int] + assert option.default is tanjun.abc.NO_PASS + assert option.empty_value is tanjun.abc.NO_DEFAULT + assert option.is_multi is False + assert option.min_length is None + assert option.max_length is None + assert option.min_value is None + assert option.max_value is None + + +def test_when_annotated_handles_typing_unions(): @annotations.with_annotated_args(follow_wrapped=True) @tanjun.as_slash_command("name", "description") @tanjun.as_message_command("name") @@ -4824,78 +4821,76 @@ async def command( assert option.max_value is None -if sys.version_info >= (3, 10): +def test_when_annotated_handles_3_10_unions(): + @annotations.with_annotated_args(follow_wrapped=True) + @tanjun.as_slash_command("name", "description") + @tanjun.as_message_command("name") + async def command( + ctx: tanjun.abc.Context, + *, + value: typing.Annotated[annotations.Str | bool, annotations.Positional(), "nyaa"] = False, + other_value: typing.Annotated[annotations.Int | None, "meow"] = None, + ) -> None: + raise NotImplementedError - def test_when_annotated_handles_3_10_unions(): - @annotations.with_annotated_args(follow_wrapped=True) - @tanjun.as_slash_command("name", "description") - @tanjun.as_message_command("name") - async def command( - ctx: tanjun.abc.Context, - *, - value: typing.Annotated[annotations.Str | bool, annotations.Positional(), "nyaa"] = False, - other_value: typing.Annotated[annotations.Int | None, "meow"] = None, - ) -> None: - raise NotImplementedError - - assert command.build().options == [ - hikari.CommandOption(type=hikari.OptionType.STRING, name="value", description="nyaa", is_required=False), - hikari.CommandOption( - type=hikari.OptionType.INTEGER, - name="other_value", - description="meow", - is_required=False, - min_value=None, - max_value=None, - ), - ] - - assert len(command._tracked_options) == 2 - tracked_option = command._tracked_options["value"] - assert tracked_option.converters == [] - assert tracked_option.default is tanjun.abc.NO_PASS - assert tracked_option.is_always_float is False - assert tracked_option.is_only_member is False - assert tracked_option.key == "value" - assert tracked_option.name == "value" - assert tracked_option.type is hikari.OptionType.STRING - - tracked_option = command._tracked_options["other_value"] - assert tracked_option.converters == [] - assert tracked_option.default is tanjun.abc.NO_PASS - assert tracked_option.is_always_float is False - assert tracked_option.is_only_member is False - assert tracked_option.key == "other_value" - assert tracked_option.name == "other_value" - assert tracked_option.type is hikari.OptionType.INTEGER - - assert isinstance(command.wrapped_command, tanjun.MessageCommand) - assert isinstance(command.wrapped_command.parser, tanjun.ShlexParser) - - assert len(command.wrapped_command.parser.arguments) == 1 - argument = command.wrapped_command.parser.arguments[0] - assert argument.key == "value" - assert argument.converters == [] - assert argument.default is tanjun.abc.NO_PASS - assert argument.is_greedy is False - assert argument.is_multi is False - assert argument.min_length is None - assert argument.max_length is None - assert argument.min_value is None - assert argument.max_value is None - - assert len(command.wrapped_command.parser.options) == 1 - option = command.wrapped_command.parser.options[0] - assert option.key == "other_value" - assert option.names == ["--other-value"] - assert option.converters == [int] - assert option.default is tanjun.abc.NO_PASS - assert option.empty_value is tanjun.abc.NO_DEFAULT - assert option.is_multi is False - assert option.min_length is None - assert option.max_length is None - assert option.min_value is None - assert option.max_value is None + assert command.build().options == [ + hikari.CommandOption(type=hikari.OptionType.STRING, name="value", description="nyaa", is_required=False), + hikari.CommandOption( + type=hikari.OptionType.INTEGER, + name="other_value", + description="meow", + is_required=False, + min_value=None, + max_value=None, + ), + ] + + assert len(command._tracked_options) == 2 + tracked_option = command._tracked_options["value"] + assert tracked_option.converters == [] + assert tracked_option.default is tanjun.abc.NO_PASS + assert tracked_option.is_always_float is False + assert tracked_option.is_only_member is False + assert tracked_option.key == "value" + assert tracked_option.name == "value" + assert tracked_option.type is hikari.OptionType.STRING + + tracked_option = command._tracked_options["other_value"] + assert tracked_option.converters == [] + assert tracked_option.default is tanjun.abc.NO_PASS + assert tracked_option.is_always_float is False + assert tracked_option.is_only_member is False + assert tracked_option.key == "other_value" + assert tracked_option.name == "other_value" + assert tracked_option.type is hikari.OptionType.INTEGER + + assert isinstance(command.wrapped_command, tanjun.MessageCommand) + assert isinstance(command.wrapped_command.parser, tanjun.ShlexParser) + + assert len(command.wrapped_command.parser.arguments) == 1 + argument = command.wrapped_command.parser.arguments[0] + assert argument.key == "value" + assert argument.converters == [] + assert argument.default is tanjun.abc.NO_PASS + assert argument.is_greedy is False + assert argument.is_multi is False + assert argument.min_length is None + assert argument.max_length is None + assert argument.min_value is None + assert argument.max_value is None + + assert len(command.wrapped_command.parser.options) == 1 + option = command.wrapped_command.parser.options[0] + assert option.key == "other_value" + assert option.names == ["--other-value"] + assert option.converters == [int] + assert option.default is tanjun.abc.NO_PASS + assert option.empty_value is tanjun.abc.NO_DEFAULT + assert option.is_multi is False + assert option.min_length is None + assert option.max_length is None + assert option.min_value is None + assert option.max_value is None def test_parse_annotated_args_with_descriptions_argument(): diff --git a/tests/test_checks.py b/tests/test_checks.py index 0b16e3d02..066a90c53 100644 --- a/tests/test_checks.py +++ b/tests/test_checks.py @@ -37,9 +37,9 @@ import operator import typing from collections import abc as collections +from unittest import mock import hikari -import mock import pytest import tanjun diff --git a/tests/test_clients.py b/tests/test_clients.py index 78c70aa0d..8af3962c1 100644 --- a/tests/test_clients.py +++ b/tests/test_clients.py @@ -38,17 +38,15 @@ import inspect import pathlib import shutil -import sys import tempfile import textwrap import typing import uuid from collections import abc as collections +from unittest import mock import hikari -import mock import pytest -import typing_extensions import tanjun @@ -63,7 +61,7 @@ class TestMessageAcceptsEnum: (tanjun.MessageAcceptsEnum.NONE, None), ], ) - def test_get_event_type(self, value: tanjun.MessageAcceptsEnum, expected_type: typing.Optional[hikari.Event]): + def test_get_event_type(self, value: tanjun.MessageAcceptsEnum, expected_type: hikari.Event | None): assert value.get_event_type() == expected_type @@ -92,7 +90,7 @@ def test_load(self): mock_callback = mock.Mock() mock_client = mock.Mock(tanjun.Client) descriptor = tanjun.as_loader(mock_callback) - typing_extensions.assert_type(descriptor, collections.Callable[[tanjun.Client], None]) + typing.assert_type(descriptor, collections.Callable[[tanjun.Client], None]) assert isinstance(descriptor, tanjun.clients._LoaderDescriptor) result = descriptor.load(mock_client) @@ -104,7 +102,7 @@ def test_load_when_called_as_decorator(self): mock_callback = mock.Mock() mock_client = mock.Mock(tanjun.Client) descriptor = tanjun.as_loader()(mock_callback) - typing_extensions.assert_type(descriptor, collections.Callable[[tanjun.Client], None]) + typing.assert_type(descriptor, collections.Callable[[tanjun.Client], None]) assert isinstance(descriptor, tanjun.clients._LoaderDescriptor) result = descriptor.load(mock_client) @@ -116,7 +114,7 @@ def test_load_when_called_as_decorator_and_args_passed(self): mock_callback = mock.Mock() mock_client = mock.Mock(tanjun.Client) descriptor = tanjun.as_loader(standard_impl=True)(mock_callback) - typing_extensions.assert_type(descriptor, collections.Callable[[tanjun.Client], None]) + typing.assert_type(descriptor, collections.Callable[[tanjun.Client], None]) assert isinstance(descriptor, tanjun.clients._LoaderDescriptor) result = descriptor.load(mock_client) @@ -127,7 +125,7 @@ def test_load_when_called_as_decorator_and_args_passed(self): def test_load_when_must_be_std_and_not_std(self): mock_callback = mock.Mock() descriptor = tanjun.as_loader(mock_callback) - typing_extensions.assert_type(descriptor, collections.Callable[[tanjun.Client], None]) + typing.assert_type(descriptor, collections.Callable[[tanjun.Client], None]) assert isinstance(descriptor, tanjun.clients._LoaderDescriptor) with pytest.raises(TypeError, match="This loader requires instances of the standard Client implementation"): @@ -139,7 +137,7 @@ def test_load_when_abc_allowed(self): mock_callback = mock.Mock() mock_client = mock.Mock() descriptor = tanjun.as_loader(mock_callback, standard_impl=False) - typing_extensions.assert_type(descriptor, collections.Callable[[tanjun.abc.Client], None]) + typing.assert_type(descriptor, collections.Callable[[tanjun.abc.Client], None]) assert isinstance(descriptor, tanjun.clients._LoaderDescriptor) result = descriptor.load(mock_client) @@ -151,7 +149,7 @@ def test_load_when_abc_allowed_and_called_as_decorator(self): mock_callback = mock.Mock() mock_client = mock.Mock() descriptor = tanjun.as_loader(standard_impl=False)(mock_callback) - typing_extensions.assert_type(descriptor, collections.Callable[[tanjun.abc.Client], None]) + typing.assert_type(descriptor, collections.Callable[[tanjun.abc.Client], None]) assert isinstance(descriptor, tanjun.clients._LoaderDescriptor) result = descriptor.load(mock_client) @@ -205,7 +203,7 @@ def test_unload(self): mock_callback = mock.Mock() mock_client = mock.Mock(tanjun.Client) descriptor = tanjun.as_unloader(mock_callback) - typing_extensions.assert_type(descriptor, collections.Callable[[tanjun.Client], None]) + typing.assert_type(descriptor, collections.Callable[[tanjun.Client], None]) assert isinstance(descriptor, tanjun.clients._UnloaderDescriptor) result = descriptor.unload(mock_client) @@ -217,7 +215,7 @@ def test_unload_when_called_as_decorator(self): mock_callback = mock.Mock() mock_client = mock.Mock(tanjun.Client) descriptor = tanjun.as_unloader()(mock_callback) - typing_extensions.assert_type(descriptor, collections.Callable[[tanjun.Client], None]) + typing.assert_type(descriptor, collections.Callable[[tanjun.Client], None]) assert isinstance(descriptor, tanjun.clients._UnloaderDescriptor) result = descriptor.unload(mock_client) @@ -229,7 +227,7 @@ def test_unload_called_as_decorator_and_args_passed(self): mock_callback = mock.Mock() mock_client = mock.Mock(tanjun.Client) descriptor = tanjun.as_unloader(standard_impl=True)(mock_callback) - typing_extensions.assert_type(descriptor, collections.Callable[[tanjun.Client], None]) + typing.assert_type(descriptor, collections.Callable[[tanjun.Client], None]) assert isinstance(descriptor, tanjun.clients._UnloaderDescriptor) result = descriptor.unload(mock_client) @@ -240,7 +238,7 @@ def test_unload_called_as_decorator_and_args_passed(self): def test_unload_when_must_be_std_and_not_std(self): mock_callback = mock.Mock() descriptor = tanjun.as_unloader(mock_callback) - typing_extensions.assert_type(descriptor, collections.Callable[[tanjun.Client], None]) + typing.assert_type(descriptor, collections.Callable[[tanjun.Client], None]) assert isinstance(descriptor, tanjun.clients._UnloaderDescriptor) with pytest.raises(TypeError, match="This unloader requires instances of the standard Client implementation"): @@ -252,7 +250,7 @@ def test_unload_when_abc_allowed(self): mock_callback = mock.Mock() mock_client = mock.Mock() descriptor = tanjun.as_unloader(mock_callback, standard_impl=False) - typing_extensions.assert_type(descriptor, collections.Callable[[tanjun.abc.Client], None]) + typing.assert_type(descriptor, collections.Callable[[tanjun.abc.Client], None]) assert isinstance(descriptor, tanjun.clients._UnloaderDescriptor) result = descriptor.unload(mock_client) @@ -264,7 +262,7 @@ def test_unload_when_abc_allowed_and_called_as_decorator(self): mock_callback = mock.Mock() mock_client = mock.Mock() descriptor = tanjun.as_unloader(standard_impl=False)(mock_callback) - typing_extensions.assert_type(descriptor, collections.Callable[[tanjun.abc.Client], None]) + typing.assert_type(descriptor, collections.Callable[[tanjun.abc.Client], None]) assert isinstance(descriptor, tanjun.clients._UnloaderDescriptor) result = descriptor.unload(mock_client) @@ -1328,7 +1326,7 @@ class StubClient(tanjun.Client): assert result is callback add_listener_.assert_called_once_with(hikari.BanEvent, callback) - def test_with_listener_with_type_hint_union(self): + def test_with_listener_with_type_hint_typing_union(self): async def callback( event: typing.Union[hikari.RoleEvent, typing.Literal["ok"], hikari.GuildEvent, str] ) -> None: ... @@ -1345,7 +1343,7 @@ class StubClient(tanjun.Client): assert result is callback add_listener_.assert_has_calls([mock.call(hikari.RoleEvent, callback), mock.call(hikari.GuildEvent, callback)]) - def test_with_listener_with_type_hint_union_nested_annotated(self): + def test_with_listener_with_type_hint_typing_union_nested_annotated(self): async def callback( event: typing.Annotated[ typing.Union[ @@ -1375,50 +1373,45 @@ class StubClient(tanjun.Client): ] ) - # These tests covers syntax which was introduced in 3.10 - if sys.version_info >= (3, 10): + def test_with_listener_with_type_hint_310_union(self): + async def callback(event: hikari.ShardEvent | typing.Literal[""] | hikari.VoiceEvent | str) -> None: ... - def test_with_listener_with_type_hint_310_union(self): - async def callback(event: hikari.ShardEvent | typing.Literal[""] | hikari.VoiceEvent | str) -> None: ... - - add_listener_ = mock.Mock() + add_listener_ = mock.Mock() - class StubClient(tanjun.Client): - add_listener = add_listener_ + class StubClient(tanjun.Client): + add_listener = add_listener_ - client = StubClient(mock.Mock()) + client = StubClient(mock.Mock()) - result = client.with_listener()(callback) + result = client.with_listener()(callback) - assert result is callback - add_listener_.assert_has_calls( - [mock.call(hikari.ShardEvent, callback), mock.call(hikari.VoiceEvent, callback)] - ) + assert result is callback + add_listener_.assert_has_calls([mock.call(hikari.ShardEvent, callback), mock.call(hikari.VoiceEvent, callback)]) - def test_with_listener_with_type_hint_310_union_nested_annotated(self): - async def callback( - event: typing.Annotated[ - typing.Annotated[hikari.BanEvent | hikari.GuildEvent, 123, 321] | hikari.InviteEvent, True, "meow" - ] - ) -> None: ... + def test_with_listener_with_type_hint_310_union_nested_annotated(self): + async def callback( + event: typing.Annotated[ + typing.Annotated[hikari.BanEvent | hikari.GuildEvent, 123, 321] | hikari.InviteEvent, True, "meow" + ] + ) -> None: ... - add_listener_ = mock.Mock() + add_listener_ = mock.Mock() - class StubClient(tanjun.Client): - add_listener = add_listener_ + class StubClient(tanjun.Client): + add_listener = add_listener_ - client = StubClient(mock.Mock()) + client = StubClient(mock.Mock()) - result = client.with_listener()(callback) + result = client.with_listener()(callback) - assert result is callback - add_listener_.assert_has_calls( - [ - mock.call(hikari.BanEvent, callback), - mock.call(hikari.GuildEvent, callback), - mock.call(hikari.InviteEvent, callback), - ] - ) + assert result is callback + add_listener_.assert_has_calls( + [ + mock.call(hikari.BanEvent, callback), + mock.call(hikari.GuildEvent, callback), + mock.call(hikari.InviteEvent, callback), + ] + ) def test_add_prefix(self): client = tanjun.Client(mock.Mock()) @@ -5449,7 +5442,7 @@ async def test_on_command_interaction_request_for_slash_command(self, command_di mock_result = mock.Mock() task = None - async def execution_callback(ctx: tanjun.abc.SlashContext, hooks: typing.Optional[tanjun.abc.SlashHooks]): + async def execution_callback(ctx: tanjun.abc.SlashContext, hooks: tanjun.abc.SlashHooks | None): async def _(): nonlocal task assert ctx is mock_ctx_maker.return_value @@ -5513,7 +5506,7 @@ async def test_on_command_interaction_request_for_slash_command_when_future_not_ ): task = None - async def execution_callback(ctx: tanjun.abc.SlashContext, hooks: typing.Optional[tanjun.abc.SlashHooks]): + async def execution_callback(ctx: tanjun.abc.SlashContext, hooks: tanjun.abc.SlashHooks | None): async def _(): nonlocal task assert ctx is mock_ctx_maker.return_value @@ -5575,7 +5568,7 @@ async def test_on_command_interaction_request_for_slash_command_when_ephemeral_d mock_result = mock.Mock() task = None - async def execution_callback(ctx: tanjun.abc.SlashContext, hooks: typing.Optional[tanjun.abc.SlashHooks]): + async def execution_callback(ctx: tanjun.abc.SlashContext, hooks: tanjun.abc.SlashHooks | None): async def _(): nonlocal task assert ctx is mock_ctx_maker.return_value @@ -5694,7 +5687,7 @@ async def test_on_command_interaction_request_for_slash_command_when_no_hooks( mock_result = mock.Mock() task = None - async def execution_callback(ctx: tanjun.abc.SlashContext, hooks: typing.Optional[tanjun.abc.SlashHooks]): + async def execution_callback(ctx: tanjun.abc.SlashContext, hooks: tanjun.abc.SlashHooks | None): async def _(): nonlocal task assert ctx is mock_ctx_maker.return_value @@ -5755,7 +5748,7 @@ async def test_on_command_interaction_request_for_slash_command_when_only_slash_ mock_result = mock.Mock() task = None - async def execution_callback(ctx: tanjun.abc.SlashContext, hooks: typing.Optional[tanjun.abc.SlashHooks]): + async def execution_callback(ctx: tanjun.abc.SlashContext, hooks: tanjun.abc.SlashHooks | None): async def _(): nonlocal task assert ctx is mock_ctx_maker.return_value @@ -5819,7 +5812,7 @@ async def test_on_command_interaction_request_for_slash_command_when_only_generi mock_result = mock.Mock() task = None - async def execution_callback(ctx: tanjun.abc.SlashContext, hooks: typing.Optional[tanjun.abc.SlashHooks]): + async def execution_callback(ctx: tanjun.abc.SlashContext, hooks: tanjun.abc.SlashHooks | None): async def _(): nonlocal task assert ctx is mock_ctx_maker.return_value @@ -6310,7 +6303,7 @@ async def test_on_command_interaction_request_for_menu_command(self, command_dis mock_result = mock.Mock() task = None - async def execution_callback(ctx: tanjun.abc.MenuContext, hooks: typing.Optional[tanjun.abc.MenuHooks]): + async def execution_callback(ctx: tanjun.abc.MenuContext, hooks: tanjun.abc.MenuHooks | None): async def _(): nonlocal task assert ctx is mock_ctx_maker.return_value @@ -6374,7 +6367,7 @@ async def test_on_command_interaction_request_for_menu_command_when_future_not_s ): task = None - async def execution_callback(ctx: tanjun.abc.MenuContext, hooks: typing.Optional[tanjun.abc.MenuHooks]): + async def execution_callback(ctx: tanjun.abc.MenuContext, hooks: tanjun.abc.MenuHooks | None): async def _(): nonlocal task assert ctx is mock_ctx_maker.return_value @@ -6436,7 +6429,7 @@ async def test_on_command_interaction_request_for_menu_command_when_ephemeral_de mock_result = mock.Mock() task = None - async def execution_callback(ctx: tanjun.abc.MenuContext, hooks: typing.Optional[tanjun.abc.MenuHooks]): + async def execution_callback(ctx: tanjun.abc.MenuContext, hooks: tanjun.abc.MenuHooks | None): async def _(): nonlocal task assert ctx is mock_ctx_maker.return_value @@ -6555,7 +6548,7 @@ async def test_on_command_interaction_request_for_menu_command_when_no_hooks( mock_result = mock.Mock() task = None - async def execution_callback(ctx: tanjun.abc.MenuContext, hooks: typing.Optional[tanjun.abc.MenuHooks]): + async def execution_callback(ctx: tanjun.abc.MenuContext, hooks: tanjun.abc.MenuHooks | None): async def _(): nonlocal task assert ctx is mock_ctx_maker.return_value @@ -6616,7 +6609,7 @@ async def test_on_command_interaction_request_for_menu_command_when_only_menu_ho mock_result = mock.Mock() task = None - async def execution_callback(ctx: tanjun.abc.MenuContext, hooks: typing.Optional[tanjun.abc.MenuHooks]): + async def execution_callback(ctx: tanjun.abc.MenuContext, hooks: tanjun.abc.MenuHooks | None): async def _(): nonlocal task assert ctx is mock_ctx_maker.return_value @@ -6680,7 +6673,7 @@ async def test_on_command_interaction_request_for_menu_command_when_only_generic mock_result = mock.Mock() task = None - async def execution_callback(ctx: tanjun.abc.MenuContext, hooks: typing.Optional[tanjun.abc.MenuHooks]): + async def execution_callback(ctx: tanjun.abc.MenuContext, hooks: tanjun.abc.MenuHooks | None): async def _(): nonlocal task assert ctx is mock_ctx_maker.return_value diff --git a/tests/test_clients_future_annotations.py b/tests/test_clients_future_annotations.py index 316b96516..531a94526 100644 --- a/tests/test_clients_future_annotations.py +++ b/tests/test_clients_future_annotations.py @@ -31,11 +31,10 @@ from __future__ import annotations import inspect -import sys import typing +from unittest import mock import hikari -import mock import pytest import tanjun @@ -134,7 +133,7 @@ class StubClient(tanjun.Client): assert result is callback add_listener_.assert_called_once_with(hikari.BanEvent, callback) - def test_with_listener_with_type_hint_union(self): + def test_with_listener_with_type_hint_typing_union(self): async def callback( event: typing.Union[hikari.RoleEvent, typing.Literal["ok"], hikari.GuildEvent, str] ) -> None: ... @@ -151,7 +150,7 @@ class StubClient(tanjun.Client): assert result is callback add_listener_.assert_has_calls([mock.call(hikari.RoleEvent, callback), mock.call(hikari.GuildEvent, callback)]) - def test_with_listener_with_type_hint_union_nested_annotated(self): + def test_with_listener_with_type_hint_typing_union_nested_annotated(self): async def callback( event: typing.Annotated[ typing.Union[ @@ -181,47 +180,42 @@ class StubClient(tanjun.Client): ] ) - # These tests covers syntax which was introduced in 3.10 - if sys.version_info >= (3, 10): + def test_with_listener_with_type_hint_310_union(self): + async def callback(event: hikari.ShardEvent | typing.Literal[""] | hikari.VoiceEvent | str) -> None: ... - def test_with_listener_with_type_hint_310_union(self): - async def callback(event: hikari.ShardEvent | typing.Literal[""] | hikari.VoiceEvent | str) -> None: ... - - add_listener_ = mock.Mock() + add_listener_ = mock.Mock() - class StubClient(tanjun.Client): - add_listener = add_listener_ + class StubClient(tanjun.Client): + add_listener = add_listener_ - client = StubClient(mock.Mock()) + client = StubClient(mock.Mock()) - result = client.with_listener()(callback) + result = client.with_listener()(callback) - assert result is callback - add_listener_.assert_has_calls( - [mock.call(hikari.ShardEvent, callback), mock.call(hikari.VoiceEvent, callback)] - ) + assert result is callback + add_listener_.assert_has_calls([mock.call(hikari.ShardEvent, callback), mock.call(hikari.VoiceEvent, callback)]) - def test_with_listener_with_type_hint_310_union_nested_annotated(self): - async def callback( - event: typing.Annotated[ - typing.Annotated[hikari.BanEvent | hikari.GuildEvent, 123, 321] | hikari.InviteEvent, True, "meow" - ] - ) -> None: ... + def test_with_listener_with_type_hint_310_union_nested_annotated(self): + async def callback( + event: typing.Annotated[ + typing.Annotated[hikari.BanEvent | hikari.GuildEvent, 123, 321] | hikari.InviteEvent, True, "meow" + ] + ) -> None: ... - add_listener_ = mock.Mock() + add_listener_ = mock.Mock() - class StubClient(tanjun.Client): - add_listener = add_listener_ + class StubClient(tanjun.Client): + add_listener = add_listener_ - client = StubClient(mock.Mock()) + client = StubClient(mock.Mock()) - result = client.with_listener()(callback) + result = client.with_listener()(callback) - assert result is callback - add_listener_.assert_has_calls( - [ - mock.call(hikari.BanEvent, callback), - mock.call(hikari.GuildEvent, callback), - mock.call(hikari.InviteEvent, callback), - ] - ) + assert result is callback + add_listener_.assert_has_calls( + [ + mock.call(hikari.BanEvent, callback), + mock.call(hikari.GuildEvent, callback), + mock.call(hikari.InviteEvent, callback), + ] + ) diff --git a/tests/test_components.py b/tests/test_components.py index 711bc59fd..dec43556e 100644 --- a/tests/test_components.py +++ b/tests/test_components.py @@ -36,12 +36,11 @@ import asyncio import inspect -import sys import types import typing +from unittest import mock import hikari -import mock import pytest import tanjun @@ -1315,7 +1314,7 @@ async def callback(*event: hikari.BanEvent) -> None: ... assert result is callback add_listener.assert_called_once_with(hikari.BanEvent, callback) - def test_with_listener_with_type_hint_union(self): + def test_with_listener_with_type_hint_typing_union(self): async def callback( event: typing.Union[hikari.RoleEvent, typing.Literal["ok"], hikari.GuildEvent, str] ) -> None: ... @@ -1330,7 +1329,7 @@ async def callback( assert result is callback add_listener.assert_has_calls([mock.call(hikari.RoleEvent, callback), mock.call(hikari.GuildEvent, callback)]) - def test_with_listener_with_type_hint_union_nested_annotated(self): + def test_with_listener_with_type_hint_typing_union_nested_annotated(self): async def callback( event: typing.Annotated[ typing.Union[ @@ -1358,46 +1357,41 @@ async def callback( ] ) - # These tests covers syntax which was introduced in 3.10 - if sys.version_info >= (3, 10): + def test_with_listener_with_type_hint_310_union(self): + async def callback(event: hikari.ShardEvent | typing.Literal[""] | hikari.VoiceEvent | str) -> None: ... - def test_with_listener_with_type_hint_310_union(self): - async def callback(event: hikari.ShardEvent | typing.Literal[""] | hikari.VoiceEvent | str) -> None: ... - - add_listener = mock.Mock() - component: tanjun.Component = types.new_class( - "StubComponent", (tanjun.Component,), exec_body=lambda ns: ns.update({"add_listener": add_listener}) - )() + add_listener = mock.Mock() + component: tanjun.Component = types.new_class( + "StubComponent", (tanjun.Component,), exec_body=lambda ns: ns.update({"add_listener": add_listener}) + )() - result = component.with_listener()(callback) + result = component.with_listener()(callback) - assert result is callback - add_listener.assert_has_calls( - [mock.call(hikari.ShardEvent, callback), mock.call(hikari.VoiceEvent, callback)] - ) + assert result is callback + add_listener.assert_has_calls([mock.call(hikari.ShardEvent, callback), mock.call(hikari.VoiceEvent, callback)]) - def test_with_listener_with_type_hint_310_union_nested_annotated(self): - async def callback( - event: typing.Annotated[ - typing.Annotated[hikari.BanEvent | hikari.GuildEvent, 123, 321] | hikari.InviteEvent, True, "meow" - ] - ) -> None: ... + def test_with_listener_with_type_hint_310_union_nested_annotated(self): + async def callback( + event: typing.Annotated[ + typing.Annotated[hikari.BanEvent | hikari.GuildEvent, 123, 321] | hikari.InviteEvent, True, "meow" + ] + ) -> None: ... - add_listener = mock.Mock() - component: tanjun.Component = types.new_class( - "StubComponent", (tanjun.Component,), exec_body=lambda ns: ns.update({"add_listener": add_listener}) - )() + add_listener = mock.Mock() + component: tanjun.Component = types.new_class( + "StubComponent", (tanjun.Component,), exec_body=lambda ns: ns.update({"add_listener": add_listener}) + )() - result = component.with_listener()(callback) + result = component.with_listener()(callback) - assert result is callback - add_listener.assert_has_calls( - [ - mock.call(hikari.BanEvent, callback), - mock.call(hikari.GuildEvent, callback), - mock.call(hikari.InviteEvent, callback), - ] - ) + assert result is callback + add_listener.assert_has_calls( + [ + mock.call(hikari.BanEvent, callback), + mock.call(hikari.GuildEvent, callback), + mock.call(hikari.InviteEvent, callback), + ] + ) def test_add_on_close(self): mock_callback = mock.Mock() diff --git a/tests/test_components_future_annotations.py b/tests/test_components_future_annotations.py index 590e0285b..08ee4eb00 100644 --- a/tests/test_components_future_annotations.py +++ b/tests/test_components_future_annotations.py @@ -31,12 +31,11 @@ from __future__ import annotations import inspect -import sys import types import typing +from unittest import mock import hikari -import mock import pytest import tanjun @@ -123,7 +122,7 @@ async def callback(*event: hikari.BanEvent) -> None: ... assert result is callback add_listener.assert_called_once_with(hikari.BanEvent, callback) - def test_with_listener_with_type_hint_union(self): + def test_with_listener_with_type_hint_typing_union(self): async def callback( event: typing.Union[hikari.RoleEvent, typing.Literal["ok"], hikari.GuildEvent, str] ) -> None: ... @@ -138,7 +137,7 @@ async def callback( assert result is callback add_listener.assert_has_calls([mock.call(hikari.RoleEvent, callback), mock.call(hikari.GuildEvent, callback)]) - def test_with_listener_with_type_hint_union_nested_annotated(self): + def test_with_listener_with_type_hint_typing_union_nested_annotated(self): async def callback( event: typing.Annotated[ typing.Union[ @@ -166,43 +165,38 @@ async def callback( ] ) - # These tests covers syntax which was introduced in 3.10 - if sys.version_info >= (3, 10): - - def test_with_listener_with_type_hint_310_union(self): - async def callback(event: hikari.ShardEvent | typing.Literal[""] | hikari.VoiceEvent | str) -> None: ... - - add_listener = mock.Mock() - component: tanjun.Component = types.new_class( - "StubComponent", (tanjun.Component,), exec_body=lambda ns: ns.update({"add_listener": add_listener}) - )() - - result = component.with_listener()(callback) - - assert result is callback - add_listener.assert_has_calls( - [mock.call(hikari.ShardEvent, callback), mock.call(hikari.VoiceEvent, callback)] - ) - - def test_with_listener_with_type_hint_310_union_nested_annotated(self): - async def callback( - event: typing.Annotated[ - typing.Annotated[hikari.BanEvent | hikari.GuildEvent, 123, 321] | hikari.InviteEvent, True, "meow" - ] - ) -> None: ... - - add_listener = mock.Mock() - component: tanjun.Component = types.new_class( - "StubComponent", (tanjun.Component,), exec_body=lambda ns: ns.update({"add_listener": add_listener}) - )() - - result = component.with_listener()(callback) - - assert result is callback - add_listener.assert_has_calls( - [ - mock.call(hikari.BanEvent, callback), - mock.call(hikari.GuildEvent, callback), - mock.call(hikari.InviteEvent, callback), - ] - ) + def test_with_listener_with_type_hint_310_union(self): + async def callback(event: hikari.ShardEvent | typing.Literal[""] | hikari.VoiceEvent | str) -> None: ... + + add_listener = mock.Mock() + component: tanjun.Component = types.new_class( + "StubComponent", (tanjun.Component,), exec_body=lambda ns: ns.update({"add_listener": add_listener}) + )() + + result = component.with_listener()(callback) + + assert result is callback + add_listener.assert_has_calls([mock.call(hikari.ShardEvent, callback), mock.call(hikari.VoiceEvent, callback)]) + + def test_with_listener_with_type_hint_310_union_nested_annotated(self): + async def callback( + event: typing.Annotated[ + typing.Annotated[hikari.BanEvent | hikari.GuildEvent, 123, 321] | hikari.InviteEvent, True, "meow" + ] + ) -> None: ... + + add_listener = mock.Mock() + component: tanjun.Component = types.new_class( + "StubComponent", (tanjun.Component,), exec_body=lambda ns: ns.update({"add_listener": add_listener}) + )() + + result = component.with_listener()(callback) + + assert result is callback + add_listener.assert_has_calls( + [ + mock.call(hikari.BanEvent, callback), + mock.call(hikari.GuildEvent, callback), + mock.call(hikari.InviteEvent, callback), + ] + ) diff --git a/tests/test_conversion.py b/tests/test_conversion.py index 10275eacd..c7dc8fce5 100644 --- a/tests/test_conversion.py +++ b/tests/test_conversion.py @@ -36,10 +36,10 @@ import datetime import typing import urllib.parse +from unittest import mock import freezegun import hikari -import mock import pytest import tanjun @@ -1570,7 +1570,7 @@ async def test___call___when_in_a_dm(self): ("", 22222), ], ) -def test_parse_snowflake(value: typing.Union[str, int], result: int): +def test_parse_snowflake(value: str | int, result: int): assert tanjun.conversion.parse_snowflake(value) == result @@ -1593,7 +1593,7 @@ def test_parse_snowflake(value: typing.Union[str, int], result: int): "", ], ) -def test_parse_snowflake_with_invalid_value(value: typing.Union[int, str]): +def test_parse_snowflake_with_invalid_value(value: int | str): with pytest.raises(ValueError, match="abcas"): tanjun.conversion.parse_snowflake(value, message="abcas") @@ -1608,7 +1608,7 @@ def test_search_snowflakes(): @pytest.mark.parametrize(("value", "result"), [("43123", 43123), (1233211, 1233211), ("<#12333>", 12333)]) -def test_parse_channel_id(value: typing.Union[str, int], result: int): +def test_parse_channel_id(value: str | int, result: int): assert tanjun.conversion.parse_channel_id(value) == result @@ -1632,7 +1632,7 @@ def test_parse_channel_id(value: typing.Union[str, int], result: int): str(TOO_SMALL_SF), ], ) -def test_parse_channel_id_with_invalid_data(value: typing.Union[str, int]): +def test_parse_channel_id_with_invalid_data(value: str | int): with pytest.raises(ValueError, match="a message"): tanjun.conversion.parse_channel_id(value, message="a message") @@ -1648,7 +1648,7 @@ def test_search_channel_ids(): @pytest.mark.parametrize( ("value", "result"), [("43123", 43123), (1233211, 1233211), ("", 12333), ("<:name:32123>", 32123)] ) -def test_parse_emoji_id(value: typing.Union[str, int], result: int): +def test_parse_emoji_id(value: str | int, result: int): assert tanjun.conversion.parse_emoji_id(value) == result @@ -1669,7 +1669,7 @@ def test_parse_emoji_id(value: typing.Union[str, int], result: int): "<@!43123>", ], ) -def test_parse_emoji_id_with_invalid_values(value: typing.Union[str, int]): +def test_parse_emoji_id_with_invalid_values(value: str | int): with pytest.raises(ValueError, match="a messages"): tanjun.conversion.parse_emoji_id(value, message="a messages") @@ -1686,7 +1686,7 @@ def test_search_emoji_ids(): @pytest.mark.parametrize(("value", "result"), [("43123", 43123), (1233211, 1233211), ("<@&1234321>", 1234321)]) -def test_parse_role_id(value: typing.Union[str, int], result: int): +def test_parse_role_id(value: str | int, result: int): assert tanjun.conversion.parse_role_id(value) == result @@ -1710,7 +1710,7 @@ def test_parse_role_id(value: typing.Union[str, int], result: int): "", ], ) -def test_parse_role_id_with_invalid_values(value: typing.Union[int, str]): +def test_parse_role_id_with_invalid_values(value: int | str): with pytest.raises(ValueError, match="a messaged"): tanjun.conversion.parse_role_id(value, message="a messaged") @@ -1726,7 +1726,7 @@ def test_search_role_ids(): @pytest.mark.parametrize( ("value", "expected"), [("43123", 43123), ("<@!33333>", 33333), (1233211, 1233211), ("<@1234321>", 1234321)] ) -def test_parse_user_id(value: typing.Union[int, str], expected: int): +def test_parse_user_id(value: int | str, expected: int): assert tanjun.conversion.parse_user_id(value) == expected @@ -1750,7 +1750,7 @@ def test_parse_user_id(value: typing.Union[int, str], expected: int): "<:fdas:123>", ], ) -def test_parse_user_id_with_invalid_values(value: typing.Union[int, str]): +def test_parse_user_id_with_invalid_values(value: int | str): with pytest.raises(ValueError, match="a"): tanjun.conversion.parse_user_id(value, message="a") @@ -1772,7 +1772,7 @@ def test_search_user_ids(): ("@me/1234/1234", (1234, 1234)), ], ) -def test_parse_message_id(value: typing.Union[int, str], expected: tuple[typing.Optional[int], int]): +def test_parse_message_id(value: int | str, expected: tuple[int | None, int]): assert tanjun.conversion.parse_message_id(value) == expected diff --git a/tests/test_errors.py b/tests/test_errors.py index e08f0029a..85b29c4d0 100644 --- a/tests/test_errors.py +++ b/tests/test_errors.py @@ -33,8 +33,9 @@ # pyright: reportUnknownMemberType=none # This leads to too many false-positives around mocks. +from unittest import mock + import hikari -import mock import pytest import tanjun diff --git a/tests/test_hooks.py b/tests/test_hooks.py index d59908086..d2878a760 100644 --- a/tests/test_hooks.py +++ b/tests/test_hooks.py @@ -33,7 +33,8 @@ # pyright: reportPrivateUsage=none # This leads to too many false-positives around mocks. -import mock +from unittest import mock + import pytest import tanjun diff --git a/tests/test_injecting.py b/tests/test_injecting.py index c04c9c150..5232f5b70 100644 --- a/tests/test_injecting.py +++ b/tests/test_injecting.py @@ -31,8 +31,9 @@ # pyright: reportPrivateUsage=none +from unittest import mock + import alluka -import mock import pytest import tanjun diff --git a/tests/test_schedules.py b/tests/test_schedules.py index e251ad032..b5a011a07 100644 --- a/tests/test_schedules.py +++ b/tests/test_schedules.py @@ -42,10 +42,10 @@ import types import typing from collections import abc as collections +from unittest import mock import alluka import freezegun -import mock import pytest import tanjun @@ -172,7 +172,7 @@ def test_is_alive_when_is_alive(self): @pytest.mark.parametrize( "interval", [datetime.timedelta(days=7, hours=13, minutes=8, seconds=54), 652134, 652134.0] ) - def test_interval_property(self, interval: typing.Union[int, float, datetime.timedelta]): + def test_interval_property(self, interval: int | float | datetime.timedelta): interval_ = tanjun.schedules.IntervalSchedule(mock.Mock(), interval) assert interval_.interval == datetime.timedelta(days=7, hours=13, minutes=8, seconds=54) @@ -352,7 +352,7 @@ async def test__loop_when_max_runs(self): mock_client = alluka.Client() call_times: list[int] = [] close_event = asyncio.Event() - close_time: typing.Optional[int] = None + close_time: int | None = None @_print_tb async def callback() -> None: From f6131ee0f0c37a368c38d6a3de3962b9546c6372 Mon Sep 17 00:00:00 2001 From: "always-on-duty[bot]" <120557446+always-on-duty[bot]@users.noreply.github.com> Date: Sun, 17 Nov 2024 15:50:36 +0000 Subject: [PATCH 08/14] Freeze PR dependency changes --- dev-requirements/tests.txt | 3 --- dev-requirements/type-checking.txt | 3 --- 2 files changed, 6 deletions(-) diff --git a/dev-requirements/tests.txt b/dev-requirements/tests.txt index 193211970..505c06123 100644 --- a/dev-requirements/tests.txt +++ b/dev-requirements/tests.txt @@ -270,9 +270,6 @@ idna==3.10 ; python_full_version >= "3.11.0" and python_version < "3.14" \ iniconfig==2.0.0 ; python_full_version >= "3.11.0" and python_version < "3.14" \ --hash=sha256:2d91e135bf72d31a410b17c16da610a82cb55f6b0477d1a902134b24a455b8b3 \ --hash=sha256:b6a85871a79d2e3b22d2d1b94ac2824226a63c6b741c88f7ae975f18b6778374 -mock==5.1.0 ; python_full_version >= "3.11.0" and python_version < "3.14" \ - --hash=sha256:18c694e5ae8a208cdb3d2c20a993ca1a7b0efa258c247a1e565150f477f83744 \ - --hash=sha256:5e96aad5ccda4718e0a229ed94b2024df75cc2d55575ba5762d31f5767b8767d multidict==6.1.0 ; python_full_version >= "3.11.0" and python_version < "3.14" \ --hash=sha256:052e10d2d37810b99cc170b785945421141bf7bb7d2f8799d431e7db229c385f \ --hash=sha256:06809f4f0f7ab7ea2cabf9caca7d79c22c0758b58a71f9d32943ae13c7ace056 \ diff --git a/dev-requirements/type-checking.txt b/dev-requirements/type-checking.txt index 295d35462..1b12f1153 100644 --- a/dev-requirements/type-checking.txt +++ b/dev-requirements/type-checking.txt @@ -279,9 +279,6 @@ idna==3.10 ; python_full_version >= "3.11.0" and python_version < "3.14" \ iniconfig==2.0.0 ; python_full_version >= "3.11.0" and python_version < "3.14" \ --hash=sha256:2d91e135bf72d31a410b17c16da610a82cb55f6b0477d1a902134b24a455b8b3 \ --hash=sha256:b6a85871a79d2e3b22d2d1b94ac2824226a63c6b741c88f7ae975f18b6778374 -mock==5.1.0 ; python_full_version >= "3.11.0" and python_version < "3.14" \ - --hash=sha256:18c694e5ae8a208cdb3d2c20a993ca1a7b0efa258c247a1e565150f477f83744 \ - --hash=sha256:5e96aad5ccda4718e0a229ed94b2024df75cc2d55575ba5762d31f5767b8767d multidict==6.1.0 ; python_full_version >= "3.11.0" and python_version < "3.14" \ --hash=sha256:052e10d2d37810b99cc170b785945421141bf7bb7d2f8799d431e7db229c385f \ --hash=sha256:06809f4f0f7ab7ea2cabf9caca7d79c22c0758b58a71f9d32943ae13c7ace056 \ From c984b7592014c392a55fd52b143dbc3442f18b68 Mon Sep 17 00:00:00 2001 From: Faster Speeding Date: Sun, 17 Nov 2024 16:02:19 +0000 Subject: [PATCH 09/14] Small fixes --- CHANGELOG.md | 3 +++ CONTRIBUTING.md | 4 ++-- tests/commands/test_base.py | 2 +- tests/commands/test_menu.py | 2 +- tests/commands/test_message.py | 2 +- tests/commands/test_slash.py | 2 +- tests/context/test_autocomplete.py | 3 ++- tests/context/test_base.py | 2 +- tests/context/test_menu.py | 3 ++- tests/context/test_message.py | 2 +- tests/context/test_slash.py | 2 +- tests/dependencies/test___init__.py | 6 +++--- tests/dependencies/test_callbacks.py | 6 +++--- tests/dependencies/test_data.py | 2 +- tests/dependencies/test_limiters.py | 2 +- tests/dependencies/test_locales.py | 3 ++- tests/dependencies/test_owners.py | 2 +- tests/test__internal/test_cache.py | 3 ++- tests/test__internal/test_init.py | 2 +- tests/test_clients.py | 14 +++++++------- 20 files changed, 37 insertions(+), 30 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index f398bbf11..45b66252a 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -9,6 +9,9 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 - Moved away from using `typing.runtime_checkable` as this is unreliable in newer Python versions. +### Removed +- Support for Python 3.9 and 3.10. + ## [2.17.6] - 2024-10-07 ### Changed - Support Python 3.13. diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index 3e56a62ea..1557516ce 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -36,7 +36,7 @@ A few examples of pdoc style would be: always be in the style of `` [link.to.thing][] `` with no type information included. * Documenting fluent methods: The return type for fluent methods should be given as `Self` with the description for it following the lines of something like "the {x} instance to enable chained calls". -* Union types sohuld be annotated in code and documentation using `|` style and `T | None`/`T | hikari.UndefinedType` +* Union types should be annotated in code and documentation using `|` style and `T | None`/`T | hikari.UndefinedType` are preferred over `T | None`/`hikari.UndefinedOr[T]` ### CHANGELOG.md @@ -65,7 +65,7 @@ good references for how projects should be type-hinted to be `type-complete`. * This project deviates from the common convention of importing types from the typing module and instead imports the typing module itself to use generics and types in it like `typing.Annotated`. -* Since this project supports python 3.9+, the `typing` types which were deprecated by +* Since this project supports python 3.11+, the `typing` types which were deprecated by [PEP 585](https://www.python.org/dev/peps/pep-0585/) should be avoided in favour of their `collections.abc`, builtin, `re` and `contextlib` equivalents. * The standard approach for using `collections.abc` types within this project is to `import collections.abc as collections`. diff --git a/tests/commands/test_base.py b/tests/commands/test_base.py index d5567816f..df4790a60 100644 --- a/tests/commands/test_base.py +++ b/tests/commands/test_base.py @@ -37,8 +37,8 @@ import types import typing from collections import abc as collections +from unittest import mock -import mock import pytest from tanjun.commands import base as base_command diff --git a/tests/commands/test_menu.py b/tests/commands/test_menu.py index bf72d3192..2b8949ec1 100644 --- a/tests/commands/test_menu.py +++ b/tests/commands/test_menu.py @@ -35,9 +35,9 @@ # This leads to too many false-positives around mocks. import typing +from unittest import mock import hikari -import mock import pytest import tanjun diff --git a/tests/commands/test_message.py b/tests/commands/test_message.py index 44278bad7..eb01dde64 100644 --- a/tests/commands/test_message.py +++ b/tests/commands/test_message.py @@ -38,9 +38,9 @@ import types import typing from collections import abc as collections +from unittest import mock import hikari -import mock import pytest import tanjun diff --git a/tests/commands/test_slash.py b/tests/commands/test_slash.py index 193082fcc..c9b60b4b0 100644 --- a/tests/commands/test_slash.py +++ b/tests/commands/test_slash.py @@ -40,9 +40,9 @@ import types import typing from collections import abc as collections +from unittest import mock import hikari -import mock import pytest import tanjun diff --git a/tests/context/test_autocomplete.py b/tests/context/test_autocomplete.py index 921f04187..b279c6300 100644 --- a/tests/context/test_autocomplete.py +++ b/tests/context/test_autocomplete.py @@ -33,8 +33,9 @@ # pyright: reportPrivateUsage=none # This leads to too many false-positives around mocks. +from unittest import mock + import hikari -import mock import pytest from hikari import traits diff --git a/tests/context/test_base.py b/tests/context/test_base.py index 9b10db387..b26500d85 100644 --- a/tests/context/test_base.py +++ b/tests/context/test_base.py @@ -36,10 +36,10 @@ import types import typing from collections import abc as collections +from unittest import mock import alluka import hikari -import mock import pytest from hikari import traits diff --git a/tests/context/test_menu.py b/tests/context/test_menu.py index 32c284cd2..6fa99c39f 100644 --- a/tests/context/test_menu.py +++ b/tests/context/test_menu.py @@ -33,8 +33,9 @@ # pyright: reportPrivateUsage=none # This leads to too many false-positives around mocks. +from unittest import mock + import hikari -import mock import pytest import tanjun diff --git a/tests/context/test_message.py b/tests/context/test_message.py index e92da8f42..3eb330dda 100644 --- a/tests/context/test_message.py +++ b/tests/context/test_message.py @@ -38,10 +38,10 @@ import types import typing from collections import abc as collections +from unittest import mock import alluka import hikari -import mock import pytest import tanjun diff --git a/tests/context/test_slash.py b/tests/context/test_slash.py index 45978b9e7..3ad43bac5 100644 --- a/tests/context/test_slash.py +++ b/tests/context/test_slash.py @@ -38,10 +38,10 @@ import types import typing from collections import abc as collections +from unittest import mock import alluka import hikari -import mock import pytest import tanjun diff --git a/tests/dependencies/test___init__.py b/tests/dependencies/test___init__.py index fd0dba3d4..3bb38ff13 100644 --- a/tests/dependencies/test___init__.py +++ b/tests/dependencies/test___init__.py @@ -29,12 +29,12 @@ # OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE # OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -import hikari - # pyright: reportUnknownMemberType=none # pyright: reportPrivateUsage=none # This leads to too many false-positives around mocks. -import mock +from unittest import mock + +import hikari import tanjun diff --git a/tests/dependencies/test_callbacks.py b/tests/dependencies/test_callbacks.py index 9ae6ffbc0..cdb02868c 100644 --- a/tests/dependencies/test_callbacks.py +++ b/tests/dependencies/test_callbacks.py @@ -29,12 +29,12 @@ # OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE # OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -import hikari - # pyright: reportUnknownMemberType=none # pyright: reportPrivateUsage=none # This leads to too many false-positives around mocks. -import mock +from unittest import mock + +import hikari import pytest import tanjun diff --git a/tests/dependencies/test_data.py b/tests/dependencies/test_data.py index a57bb3873..3892d8688 100644 --- a/tests/dependencies/test_data.py +++ b/tests/dependencies/test_data.py @@ -36,9 +36,9 @@ import datetime import time import typing +from unittest import mock import alluka -import mock import pytest import tanjun diff --git a/tests/dependencies/test_limiters.py b/tests/dependencies/test_limiters.py index 9225b0e2d..c26e2754b 100644 --- a/tests/dependencies/test_limiters.py +++ b/tests/dependencies/test_limiters.py @@ -36,10 +36,10 @@ import datetime import re import typing +from unittest import mock import freezegun import hikari -import mock import pytest import tanjun diff --git a/tests/dependencies/test_locales.py b/tests/dependencies/test_locales.py index 3b18284ca..6adbb48a2 100644 --- a/tests/dependencies/test_locales.py +++ b/tests/dependencies/test_locales.py @@ -30,8 +30,9 @@ # OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +from unittest import mock + import hikari -import mock import tanjun diff --git a/tests/dependencies/test_owners.py b/tests/dependencies/test_owners.py index 86e3be886..d71c65d60 100644 --- a/tests/dependencies/test_owners.py +++ b/tests/dependencies/test_owners.py @@ -35,9 +35,9 @@ import asyncio import datetime import time +from unittest import mock import hikari -import mock import pytest import tanjun diff --git a/tests/test__internal/test_cache.py b/tests/test__internal/test_cache.py index 4f036dc39..e4d3be573 100644 --- a/tests/test__internal/test_cache.py +++ b/tests/test__internal/test_cache.py @@ -32,8 +32,9 @@ # pyright: reportUnknownMemberType=none # This leads to too many false-positives around mocks. +from unittest import mock + import hikari -import mock import pytest import tanjun diff --git a/tests/test__internal/test_init.py b/tests/test__internal/test_init.py index c2769096e..7b56b89ca 100644 --- a/tests/test__internal/test_init.py +++ b/tests/test__internal/test_init.py @@ -34,9 +34,9 @@ import inspect import typing +from unittest import mock import hikari -import mock import pytest import tanjun diff --git a/tests/test_clients.py b/tests/test_clients.py index 8af3962c1..32b5e3bf1 100644 --- a/tests/test_clients.py +++ b/tests/test_clients.py @@ -3118,7 +3118,7 @@ def test__reload_modules_with_system_path(self, temp_file: typing.IO[str]): temp_file.write( textwrap.dedent( """ - import mock + from unittest import mock import tanjun @@ -3172,7 +3172,7 @@ def test__reload_modules_with_system_path_when_no_unloaders_found(self, temp_fil temp_file.write( textwrap.dedent( """ - import mock + from unittest import mock import tanjun @@ -3210,7 +3210,7 @@ def test__reload_modules_with_system_path_when_no_loaders_found_in_new_module(se temp_file.write( textwrap.dedent( """ - import mock + from unittest import mock import tanjun @@ -3252,7 +3252,7 @@ def test__reload_modules_with_system_path_when_all(self, temp_file: typing.IO[st temp_file.write( textwrap.dedent( """ - import mock + from unittest import mock import tanjun @@ -3307,7 +3307,7 @@ def test__reload_modules_with_system_path_when_all_and_no_unloaders_found(self, temp_file.write( textwrap.dedent( """ - import mock + from unittest import mock import tanjun @@ -3350,7 +3350,7 @@ def test__reload_modules_with_system_path_when_all_and_no_loaders_found_in_new_m temp_file.write( textwrap.dedent( """ - import mock + from unittest import mock import tanjun @@ -3435,7 +3435,7 @@ def test__reload_modules_with_system_path_rolls_back_when_new_module_loader_rais temp_file.write( textwrap.dedent( """ - import mock + from unittest import mock import tanjun From 186a9667697034ce2af6cdc25b08452a1d424815 Mon Sep 17 00:00:00 2001 From: Faster Speeding Date: Sun, 17 Nov 2024 18:28:11 +0000 Subject: [PATCH 10/14] Remove 3.14-dev --- pyproject.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pyproject.toml b/pyproject.toml index a090c3f20..89ac710d7 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -160,7 +160,7 @@ top_level_targets = ["./docs_src", "./examples", "./noxfile.py", "./tanjun", "./ [tool.piped.github_actions.publish] [tool.piped.github_actions.py_test] codeclimate_token = "117363998d7c6b4bab4ac57348026e1089767e142ccca3eb8cc37da6cf4cc8b9" -python_versions = ["3.11", "3.12", "3.13", "3.14-dev"] +python_versions = ["3.11", "3.12", "3.13"] [tool.piped.github_actions.reformat] [tool.piped.github_actions.release_docs] From 31325f57fdf68aecc3216948c67b4eb8ce2cbd5f Mon Sep 17 00:00:00 2001 From: "always-on-duty[bot]" <120557446+always-on-duty[bot]@users.noreply.github.com> Date: Sun, 17 Nov 2024 18:28:50 +0000 Subject: [PATCH 11/14] Resync piped --- .github/workflows/py-test.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/py-test.yml b/.github/workflows/py-test.yml index 2d3489181..75f19f696 100644 --- a/.github/workflows/py-test.yml +++ b/.github/workflows/py-test.yml @@ -21,7 +21,7 @@ jobs: fail-fast: false matrix: os: [ubuntu-latest, macos-latest, windows-latest] - python-version: ["3.11", "3.12", "3.13", "3.14-dev"] + python-version: ["3.11", "3.12", "3.13"] runs-on: ${{ matrix.os }} From e475c7654c2b313ec2bdbe85581046bac801ed85 Mon Sep 17 00:00:00 2001 From: "always-on-duty[bot]" <120557446+always-on-duty[bot]@users.noreply.github.com> Date: Sun, 17 Nov 2024 18:29:02 +0000 Subject: [PATCH 12/14] Freeze PR dependency changes --- dev-requirements/constraints.txt | 166 ++++++++++++++--------------- dev-requirements/tests.txt | 166 ++++++++++++++--------------- dev-requirements/type-checking.txt | 166 ++++++++++++++--------------- 3 files changed, 249 insertions(+), 249 deletions(-) diff --git a/dev-requirements/constraints.txt b/dev-requirements/constraints.txt index 7cb995ba0..ed1d7b2c8 100644 --- a/dev-requirements/constraints.txt +++ b/dev-requirements/constraints.txt @@ -393,86 +393,86 @@ propcache==0.2.0 ; python_full_version >= "3.11.0" and python_version < "3.14" \ typing-extensions==4.12.2 ; python_full_version >= "3.11.0" and python_version < "3.14" \ --hash=sha256:04e5ca0351e0f3f85c6853954072df659d0d13fac324d0072316b67d7794700d \ --hash=sha256:1a7ead55c7e559dd4dee8856e3a88b41225abfe1ce8df57b7c13915fe121ffb8 -yarl==1.17.1 ; python_full_version >= "3.11.0" and python_version < "3.14" \ - --hash=sha256:06157fb3c58f2736a5e47c8fcbe1afc8b5de6fb28b14d25574af9e62150fcaac \ - --hash=sha256:067a63fcfda82da6b198fa73079b1ca40b7c9b7994995b6ee38acda728b64d47 \ - --hash=sha256:0b1794853124e2f663f0ea54efb0340b457f08d40a1cef78edfa086576179c91 \ - --hash=sha256:0bdff5e0995522706c53078f531fb586f56de9c4c81c243865dd5c66c132c3b5 \ - --hash=sha256:117ed8b3732528a1e41af3aa6d4e08483c2f0f2e3d3d7dca7cf538b3516d93df \ - --hash=sha256:14bc88baa44e1f84164a392827b5defb4fa8e56b93fecac3d15315e7c8e5d8b3 \ - --hash=sha256:1654ec814b18be1af2c857aa9000de7a601400bd4c9ca24629b18486c2e35463 \ - --hash=sha256:16bca6678a83657dd48df84b51bd56a6c6bd401853aef6d09dc2506a78484c7b \ - --hash=sha256:1a3b91c44efa29e6c8ef8a9a2b583347998e2ba52c5d8280dbd5919c02dfc3b5 \ - --hash=sha256:1a52a1ffdd824fb1835272e125385c32fd8b17fbdefeedcb4d543cc23b332d74 \ - --hash=sha256:1ce36ded585f45b1e9bb36d0ae94765c6608b43bd2e7f5f88079f7a85c61a4d3 \ - --hash=sha256:299f11b44d8d3a588234adbe01112126010bd96d9139c3ba7b3badd9829261c3 \ - --hash=sha256:2b24ec55fad43e476905eceaf14f41f6478780b870eda5d08b4d6de9a60b65b4 \ - --hash=sha256:2d374d70fdc36f5863b84e54775452f68639bc862918602d028f89310a034ab0 \ - --hash=sha256:2d9f0606baaec5dd54cb99667fcf85183a7477f3766fbddbe3f385e7fc253299 \ - --hash=sha256:2e7ba4c9377e48fb7b20dedbd473cbcbc13e72e1826917c185157a137dac9df2 \ - --hash=sha256:2f0a6423295a0d282d00e8701fe763eeefba8037e984ad5de44aa349002562ac \ - --hash=sha256:327828786da2006085a4d1feb2594de6f6d26f8af48b81eb1ae950c788d97f61 \ - --hash=sha256:380e6c38ef692b8fd5a0f6d1fa8774d81ebc08cfbd624b1bca62a4d4af2f9931 \ - --hash=sha256:3b74ff4767d3ef47ffe0cd1d89379dc4d828d4873e5528976ced3b44fe5b0a21 \ - --hash=sha256:3e844be8d536afa129366d9af76ed7cb8dfefec99f5f1c9e4f8ae542279a6dc3 \ - --hash=sha256:459e81c2fb920b5f5df744262d1498ec2c8081acdcfe18181da44c50f51312f7 \ - --hash=sha256:46ddf6e0b975cd680eb83318aa1d321cb2bf8d288d50f1754526230fcf59ba96 \ - --hash=sha256:482c122b72e3c5ec98f11457aeb436ae4aecca75de19b3d1de7cf88bc40db82f \ - --hash=sha256:561c87fea99545ef7d692403c110b2f99dced6dff93056d6e04384ad3bc46243 \ - --hash=sha256:578d00c9b7fccfa1745a44f4eddfdc99d723d157dad26764538fbdda37209857 \ - --hash=sha256:58c8e9620eb82a189c6c40cb6b59b4e35b2ee68b1f2afa6597732a2b467d7e8f \ - --hash=sha256:5b29beab10211a746f9846baa39275e80034e065460d99eb51e45c9a9495bcca \ - --hash=sha256:5d1d42556b063d579cae59e37a38c61f4402b47d70c29f0ef15cee1acaa64488 \ - --hash=sha256:5f236cb5999ccd23a0ab1bd219cfe0ee3e1c1b65aaf6dd3320e972f7ec3a39da \ - --hash=sha256:62a91aefff3d11bf60e5956d340eb507a983a7ec802b19072bb989ce120cd948 \ - --hash=sha256:64cc6e97f14cf8a275d79c5002281f3040c12e2e4220623b5759ea7f9868d6a5 \ - --hash=sha256:6f4c9156c4d1eb490fe374fb294deeb7bc7eaccda50e23775b2354b6a6739934 \ - --hash=sha256:7294e38f9aa2e9f05f765b28ffdc5d81378508ce6dadbe93f6d464a8c9594473 \ - --hash=sha256:7615058aabad54416ddac99ade09a5510cf77039a3b903e94e8922f25ed203d7 \ - --hash=sha256:7e48cdb8226644e2fbd0bdb0a0f87906a3db07087f4de77a1b1b1ccfd9e93685 \ - --hash=sha256:7f63d176a81555984e91f2c84c2a574a61cab7111cc907e176f0f01538e9ff6e \ - --hash=sha256:7f6595c852ca544aaeeb32d357e62c9c780eac69dcd34e40cae7b55bc4fb1147 \ - --hash=sha256:7fac95714b09da9278a0b52e492466f773cfe37651cf467a83a1b659be24bf71 \ - --hash=sha256:81713b70bea5c1386dc2f32a8f0dab4148a2928c7495c808c541ee0aae614d67 \ - --hash=sha256:846dd2e1243407133d3195d2d7e4ceefcaa5f5bf7278f0a9bda00967e6326b04 \ - --hash=sha256:84c063af19ef5130084db70ada40ce63a84f6c1ef4d3dbc34e5e8c4febb20822 \ - --hash=sha256:881764d610e3269964fc4bb3c19bb6fce55422828e152b885609ec176b41cf11 \ - --hash=sha256:8994b29c462de9a8fce2d591028b986dbbe1b32f3ad600b2d3e1c482c93abad6 \ - --hash=sha256:8c79e9d7e3d8a32d4824250a9c6401194fb4c2ad9a0cec8f6a96e09a582c2cc0 \ - --hash=sha256:8ee427208c675f1b6e344a1f89376a9613fc30b52646a04ac0c1f6587c7e46ec \ - --hash=sha256:949681f68e0e3c25377462be4b658500e85ca24323d9619fdc41f68d46a1ffda \ - --hash=sha256:9e275792097c9f7e80741c36de3b61917aebecc08a67ae62899b074566ff8556 \ - --hash=sha256:9fb815155aac6bfa8d86184079652c9715c812d506b22cfa369196ef4e99d1b4 \ - --hash=sha256:a2a64e62c7a0edd07c1c917b0586655f3362d2c2d37d474db1a509efb96fea1c \ - --hash=sha256:a7ac5b4984c468ce4f4a553df281450df0a34aefae02e58d77a0847be8d1e11f \ - --hash=sha256:aa46dce75078fceaf7cecac5817422febb4355fbdda440db55206e3bd288cfb8 \ - --hash=sha256:ae3476e934b9d714aa8000d2e4c01eb2590eee10b9d8cd03e7983ad65dfbfcba \ - --hash=sha256:b0341e6d9a0c0e3cdc65857ef518bb05b410dbd70d749a0d33ac0f39e81a4258 \ - --hash=sha256:b40d1bf6e6f74f7c0a567a9e5e778bbd4699d1d3d2c0fe46f4b717eef9e96b95 \ - --hash=sha256:b5c4804e4039f487e942c13381e6c27b4b4e66066d94ef1fae3f6ba8b953f383 \ - --hash=sha256:b5d6a6c9602fd4598fa07e0389e19fe199ae96449008d8304bf5d47cb745462e \ - --hash=sha256:b5f1ac7359e17efe0b6e5fec21de34145caef22b260e978336f325d5c84e6938 \ - --hash=sha256:c0167540094838ee9093ef6cc2c69d0074bbf84a432b4995835e8e5a0d984374 \ - --hash=sha256:c180ac742a083e109c1a18151f4dd8675f32679985a1c750d2ff806796165b55 \ - --hash=sha256:c73df5b6e8fabe2ddb74876fb82d9dd44cbace0ca12e8861ce9155ad3c886139 \ - --hash=sha256:c7e177c619342e407415d4f35dec63d2d134d951e24b5166afcdfd1362828e17 \ - --hash=sha256:cbad927ea8ed814622305d842c93412cb47bd39a496ed0f96bfd42b922b4a217 \ - --hash=sha256:cc353841428d56b683a123a813e6a686e07026d6b1c5757970a877195f880c2d \ - --hash=sha256:cc7c92c1baa629cb03ecb0c3d12564f172218fb1739f54bf5f3881844daadc6d \ - --hash=sha256:cc7d768260f4ba4ea01741c1b5fe3d3a6c70eb91c87f4c8761bbcce5181beafe \ - --hash=sha256:d0eea830b591dbc68e030c86a9569826145df485b2b4554874b07fea1275a199 \ - --hash=sha256:d216e5d9b8749563c7f2c6f7a0831057ec844c68b4c11cb10fc62d4fd373c26d \ - --hash=sha256:d401f07261dc5aa36c2e4efc308548f6ae943bfff20fcadb0a07517a26b196d8 \ - --hash=sha256:d6324274b4e0e2fa1b3eccb25997b1c9ed134ff61d296448ab8269f5ac068c4c \ - --hash=sha256:d8a8b74d843c2638f3864a17d97a4acda58e40d3e44b6303b8cc3d3c44ae2d29 \ - --hash=sha256:d9b6b28a57feb51605d6ae5e61a9044a31742db557a3b851a74c13bc61de5172 \ - --hash=sha256:de599af166970d6a61accde358ec9ded821234cbbc8c6413acfec06056b8e860 \ - --hash=sha256:e594b22688d5747b06e957f1ef822060cb5cb35b493066e33ceac0cf882188b7 \ - --hash=sha256:e5b078134f48552c4d9527db2f7da0b5359abd49393cdf9794017baec7506170 \ - --hash=sha256:eb6dce402734575e1a8cc0bb1509afca508a400a57ce13d306ea2c663bad1138 \ - --hash=sha256:f1790a4b1e8e8e028c391175433b9c8122c39b46e1663228158e61e6f915bf06 \ - --hash=sha256:f5efe0661b9fcd6246f27957f6ae1c0eb29bc60552820f01e970b4996e016004 \ - --hash=sha256:f9cbfbc5faca235fbdf531b93aa0f9f005ec7d267d9d738761a4d42b744ea159 \ - --hash=sha256:fbea1751729afe607d84acfd01efd95e3b31db148a181a441984ce9b3d3469da \ - --hash=sha256:fca4b4307ebe9c3ec77a084da3a9d1999d164693d16492ca2b64594340999988 \ - --hash=sha256:ff5c6771c7e3511a06555afa317879b7db8d640137ba55d6ab0d0c50425cab75 +yarl==1.17.2 ; python_full_version >= "3.11.0" and python_version < "3.14" \ + --hash=sha256:0c8e589379ef0407b10bed16cc26e7392ef8f86961a706ade0a22309a45414d7 \ + --hash=sha256:0d41c684f286ce41fa05ab6af70f32d6da1b6f0457459a56cf9e393c1c0b2217 \ + --hash=sha256:1056cadd5e850a1c026f28e0704ab0a94daaa8f887ece8dfed30f88befb87bb0 \ + --hash=sha256:11d86c6145ac5c706c53d484784cf504d7d10fa407cb73b9d20f09ff986059ef \ + --hash=sha256:170ed4971bf9058582b01a8338605f4d8c849bd88834061e60e83b52d0c76870 \ + --hash=sha256:17791acaa0c0f89323c57da7b9a79f2174e26d5debbc8c02d84ebd80c2b7bff8 \ + --hash=sha256:17931dfbb84ae18b287279c1f92b76a3abcd9a49cd69b92e946035cff06bcd20 \ + --hash=sha256:18662443c6c3707e2fc7fad184b4dc32dd428710bbe72e1bce7fe1988d4aa654 \ + --hash=sha256:187df91395c11e9f9dc69b38d12406df85aa5865f1766a47907b1cc9855b6303 \ + --hash=sha256:1fee66b32e79264f428dc8da18396ad59cc48eef3c9c13844adec890cd339db5 \ + --hash=sha256:2270d590997445a0dc29afa92e5534bfea76ba3aea026289e811bf9ed4b65a7f \ + --hash=sha256:2654caaf5584449d49c94a6b382b3cb4a246c090e72453493ea168b931206a4d \ + --hash=sha256:26bfb6226e0c157af5da16d2d62258f1ac578d2899130a50433ffee4a5dfa673 \ + --hash=sha256:2941756754a10e799e5b87e2319bbec481ed0957421fba0e7b9fb1c11e40509f \ + --hash=sha256:3294f787a437cb5d81846de3a6697f0c35ecff37a932d73b1fe62490bef69211 \ + --hash=sha256:358dc7ddf25e79e1cc8ee16d970c23faee84d532b873519c5036dbb858965795 \ + --hash=sha256:38bc4ed5cae853409cb193c87c86cd0bc8d3a70fd2268a9807217b9176093ac6 \ + --hash=sha256:3a0baff7827a632204060f48dca9e63fbd6a5a0b8790c1a2adfb25dc2c9c0d50 \ + --hash=sha256:3a3ede8c248f36b60227eb777eac1dbc2f1022dc4d741b177c4379ca8e75571a \ + --hash=sha256:3a58a2f2ca7aaf22b265388d40232f453f67a6def7355a840b98c2d547bd037f \ + --hash=sha256:4434b739a8a101a837caeaa0137e0e38cb4ea561f39cb8960f3b1e7f4967a3fc \ + --hash=sha256:460024cacfc3246cc4d9f47a7fc860e4fcea7d1dc651e1256510d8c3c9c7cde0 \ + --hash=sha256:46c465ad06971abcf46dd532f77560181387b4eea59084434bdff97524444032 \ + --hash=sha256:48e424347a45568413deec6f6ee2d720de2cc0385019bedf44cd93e8638aa0ed \ + --hash=sha256:4a8c83f6fcdc327783bdc737e8e45b2e909b7bd108c4da1892d3bc59c04a6d84 \ + --hash=sha256:4c840cc11163d3c01a9d8aad227683c48cd3e5be5a785921bcc2a8b4b758c4f3 \ + --hash=sha256:4d486ddcaca8c68455aa01cf53d28d413fb41a35afc9f6594a730c9779545876 \ + --hash=sha256:4e76381be3d8ff96a4e6c77815653063e87555981329cf8f85e5be5abf449021 \ + --hash=sha256:50d866f7b1a3f16f98603e095f24c0eeba25eb508c85a2c5939c8b3870ba2df8 \ + --hash=sha256:52492b87d5877ec405542f43cd3da80bdcb2d0c2fbc73236526e5f2c28e6db28 \ + --hash=sha256:56afb44a12b0864d17b597210d63a5b88915d680f6484d8d202ed68ade38673d \ + --hash=sha256:585ce7cd97be8f538345de47b279b879e091c8b86d9dbc6d98a96a7ad78876a3 \ + --hash=sha256:5870d620b23b956f72bafed6a0ba9a62edb5f2ef78a8849b7615bd9433384171 \ + --hash=sha256:5c6ea72fe619fee5e6b5d4040a451d45d8175f560b11b3d3e044cd24b2720526 \ + --hash=sha256:688058e89f512fb7541cb85c2f149c292d3fa22f981d5a5453b40c5da49eb9e8 \ + --hash=sha256:6a3f47930fbbed0f6377639503848134c4aa25426b08778d641491131351c2c8 \ + --hash=sha256:6b981316fcd940f085f646b822c2ff2b8b813cbd61281acad229ea3cbaabeb6b \ + --hash=sha256:734144cd2bd633a1516948e477ff6c835041c0536cef1d5b9a823ae29899665b \ + --hash=sha256:736bb076f7299c5c55dfef3eb9e96071a795cb08052822c2bb349b06f4cb2e0a \ + --hash=sha256:752485cbbb50c1e20908450ff4f94217acba9358ebdce0d8106510859d6eb19a \ + --hash=sha256:753eaaa0c7195244c84b5cc159dc8204b7fd99f716f11198f999f2332a86b178 \ + --hash=sha256:75ac158560dec3ed72f6d604c81090ec44529cfb8169b05ae6fcb3e986b325d9 \ + --hash=sha256:76499469dcc24759399accd85ec27f237d52dec300daaca46a5352fcbebb1071 \ + --hash=sha256:782ca9c58f5c491c7afa55518542b2b005caedaf4685ec814fadfcee51f02493 \ + --hash=sha256:792155279dc093839e43f85ff7b9b6493a8eaa0af1f94f1f9c6e8f4de8c63500 \ + --hash=sha256:7a1606ba68e311576bcb1672b2a1543417e7e0aa4c85e9e718ba6466952476c0 \ + --hash=sha256:8281db240a1616af2f9c5f71d355057e73a1409c4648c8949901396dc0a3c151 \ + --hash=sha256:871e1b47eec7b6df76b23c642a81db5dd6536cbef26b7e80e7c56c2fd371382e \ + --hash=sha256:8b9c4643e7d843a0dca9cd9d610a0876e90a1b2cbc4c5ba7930a0d90baf6903f \ + --hash=sha256:8c6d5fed96f0646bfdf698b0a1cebf32b8aae6892d1bec0c5d2d6e2df44e1e2d \ + --hash=sha256:8e1bf59e035534ba4077f5361d8d5d9194149f9ed4f823d1ee29ef3e8964ace3 \ + --hash=sha256:8fd51299e21da709eabcd5b2dd60e39090804431292daacbee8d3dabe39a6bc0 \ + --hash=sha256:91c012dceadc695ccf69301bfdccd1fc4472ad714fe2dd3c5ab4d2046afddf29 \ + --hash=sha256:93771146ef048b34201bfa382c2bf74c524980870bb278e6df515efaf93699ff \ + --hash=sha256:93d1c8cc5bf5df401015c5e2a3ce75a5254a9839e5039c881365d2a9dcfc6dc2 \ + --hash=sha256:9611b83810a74a46be88847e0ea616794c406dbcb4e25405e52bff8f4bee2d0a \ + --hash=sha256:9bc27dd5cfdbe3dc7f381b05e6260ca6da41931a6e582267d5ca540270afeeb2 \ + --hash=sha256:ac8eda86cc75859093e9ce390d423aba968f50cf0e481e6c7d7d63f90bae5c9c \ + --hash=sha256:bc3003710e335e3f842ae3fd78efa55f11a863a89a72e9a07da214db3bf7e1f8 \ + --hash=sha256:bc61b005f6521fcc00ca0d1243559a5850b9dd1e1fe07b891410ee8fe192d0c0 \ + --hash=sha256:be4c7b1c49d9917c6e95258d3d07f43cfba2c69a6929816e77daf322aaba6628 \ + --hash=sha256:c019abc2eca67dfa4d8fb72ba924871d764ec3c92b86d5b53b405ad3d6aa56b0 \ + --hash=sha256:c42774d1d1508ec48c3ed29e7b110e33f5e74a20957ea16197dbcce8be6b52ba \ + --hash=sha256:c556fbc6820b6e2cda1ca675c5fa5589cf188f8da6b33e9fc05b002e603e44fa \ + --hash=sha256:c6e659b9a24d145e271c2faf3fa6dd1fcb3e5d3f4e17273d9e0350b6ab0fe6e2 \ + --hash=sha256:c74f0b0472ac40b04e6d28532f55cac8090e34c3e81f118d12843e6df14d0909 \ + --hash=sha256:cd7e35818d2328b679a13268d9ea505c85cd773572ebb7a0da7ccbca77b6a52e \ + --hash=sha256:d17832ba39374134c10e82d137e372b5f7478c4cceeb19d02ae3e3d1daed8721 \ + --hash=sha256:d1fa68a3c921365c5745b4bd3af6221ae1f0ea1bf04b69e94eda60e57958907f \ + --hash=sha256:d63123bfd0dce5f91101e77c8a5427c3872501acece8c90df457b486bc1acd47 \ + --hash=sha256:da9d3061e61e5ae3f753654813bc1cd1c70e02fb72cf871bd6daf78443e9e2b1 \ + --hash=sha256:db5ac3871ed76340210fe028f535392f097fb31b875354bcb69162bba2632ef4 \ + --hash=sha256:dd7abf4f717e33b7487121faf23560b3a50924f80e4bef62b22dab441ded8f3b \ + --hash=sha256:dd90238d3a77a0e07d4d6ffdebc0c21a9787c5953a508a2231b5f191455f31e9 \ + --hash=sha256:ef6eee1a61638d29cd7c85f7fd3ac7b22b4c0fabc8fd00a712b727a3e73b0685 \ + --hash=sha256:f11fd61d72d93ac23718d393d2a64469af40be2116b24da0a4ca6922df26807e \ + --hash=sha256:f1e7fedb09c059efee2533119666ca7e1a2610072076926fa028c2ba5dfeb78c \ + --hash=sha256:f25b7e93f5414b9a983e1a6c1820142c13e1782cc9ed354c25e933aebe97fcf2 \ + --hash=sha256:f2f44a4247461965fed18b2573f3a9eb5e2c3cad225201ee858726cde610daca \ + --hash=sha256:f5ffc6b7ace5b22d9e73b2a4c7305740a339fbd55301d52735f73e21d9eb3130 \ + --hash=sha256:ff6af03cac0d1a4c3c19e5dcc4c05252411bf44ccaa2485e20d0a7c77892ab6e \ + --hash=sha256:ff8d95e06546c3a8c188f68040e9d0360feb67ba8498baf018918f669f7bc39b diff --git a/dev-requirements/tests.txt b/dev-requirements/tests.txt index 505c06123..d21845d65 100644 --- a/dev-requirements/tests.txt +++ b/dev-requirements/tests.txt @@ -498,86 +498,86 @@ termcolor==2.5.0 ; python_full_version >= "3.11.0" and python_version < "3.14" \ typing-extensions==4.12.2 ; python_full_version >= "3.11.0" and python_version < "3.14" \ --hash=sha256:04e5ca0351e0f3f85c6853954072df659d0d13fac324d0072316b67d7794700d \ --hash=sha256:1a7ead55c7e559dd4dee8856e3a88b41225abfe1ce8df57b7c13915fe121ffb8 -yarl==1.17.1 ; python_full_version >= "3.11.0" and python_version < "3.14" \ - --hash=sha256:06157fb3c58f2736a5e47c8fcbe1afc8b5de6fb28b14d25574af9e62150fcaac \ - --hash=sha256:067a63fcfda82da6b198fa73079b1ca40b7c9b7994995b6ee38acda728b64d47 \ - --hash=sha256:0b1794853124e2f663f0ea54efb0340b457f08d40a1cef78edfa086576179c91 \ - --hash=sha256:0bdff5e0995522706c53078f531fb586f56de9c4c81c243865dd5c66c132c3b5 \ - --hash=sha256:117ed8b3732528a1e41af3aa6d4e08483c2f0f2e3d3d7dca7cf538b3516d93df \ - --hash=sha256:14bc88baa44e1f84164a392827b5defb4fa8e56b93fecac3d15315e7c8e5d8b3 \ - --hash=sha256:1654ec814b18be1af2c857aa9000de7a601400bd4c9ca24629b18486c2e35463 \ - --hash=sha256:16bca6678a83657dd48df84b51bd56a6c6bd401853aef6d09dc2506a78484c7b \ - --hash=sha256:1a3b91c44efa29e6c8ef8a9a2b583347998e2ba52c5d8280dbd5919c02dfc3b5 \ - --hash=sha256:1a52a1ffdd824fb1835272e125385c32fd8b17fbdefeedcb4d543cc23b332d74 \ - --hash=sha256:1ce36ded585f45b1e9bb36d0ae94765c6608b43bd2e7f5f88079f7a85c61a4d3 \ - --hash=sha256:299f11b44d8d3a588234adbe01112126010bd96d9139c3ba7b3badd9829261c3 \ - --hash=sha256:2b24ec55fad43e476905eceaf14f41f6478780b870eda5d08b4d6de9a60b65b4 \ - --hash=sha256:2d374d70fdc36f5863b84e54775452f68639bc862918602d028f89310a034ab0 \ - --hash=sha256:2d9f0606baaec5dd54cb99667fcf85183a7477f3766fbddbe3f385e7fc253299 \ - --hash=sha256:2e7ba4c9377e48fb7b20dedbd473cbcbc13e72e1826917c185157a137dac9df2 \ - --hash=sha256:2f0a6423295a0d282d00e8701fe763eeefba8037e984ad5de44aa349002562ac \ - --hash=sha256:327828786da2006085a4d1feb2594de6f6d26f8af48b81eb1ae950c788d97f61 \ - --hash=sha256:380e6c38ef692b8fd5a0f6d1fa8774d81ebc08cfbd624b1bca62a4d4af2f9931 \ - --hash=sha256:3b74ff4767d3ef47ffe0cd1d89379dc4d828d4873e5528976ced3b44fe5b0a21 \ - --hash=sha256:3e844be8d536afa129366d9af76ed7cb8dfefec99f5f1c9e4f8ae542279a6dc3 \ - --hash=sha256:459e81c2fb920b5f5df744262d1498ec2c8081acdcfe18181da44c50f51312f7 \ - --hash=sha256:46ddf6e0b975cd680eb83318aa1d321cb2bf8d288d50f1754526230fcf59ba96 \ - --hash=sha256:482c122b72e3c5ec98f11457aeb436ae4aecca75de19b3d1de7cf88bc40db82f \ - --hash=sha256:561c87fea99545ef7d692403c110b2f99dced6dff93056d6e04384ad3bc46243 \ - --hash=sha256:578d00c9b7fccfa1745a44f4eddfdc99d723d157dad26764538fbdda37209857 \ - --hash=sha256:58c8e9620eb82a189c6c40cb6b59b4e35b2ee68b1f2afa6597732a2b467d7e8f \ - --hash=sha256:5b29beab10211a746f9846baa39275e80034e065460d99eb51e45c9a9495bcca \ - --hash=sha256:5d1d42556b063d579cae59e37a38c61f4402b47d70c29f0ef15cee1acaa64488 \ - --hash=sha256:5f236cb5999ccd23a0ab1bd219cfe0ee3e1c1b65aaf6dd3320e972f7ec3a39da \ - --hash=sha256:62a91aefff3d11bf60e5956d340eb507a983a7ec802b19072bb989ce120cd948 \ - --hash=sha256:64cc6e97f14cf8a275d79c5002281f3040c12e2e4220623b5759ea7f9868d6a5 \ - --hash=sha256:6f4c9156c4d1eb490fe374fb294deeb7bc7eaccda50e23775b2354b6a6739934 \ - --hash=sha256:7294e38f9aa2e9f05f765b28ffdc5d81378508ce6dadbe93f6d464a8c9594473 \ - --hash=sha256:7615058aabad54416ddac99ade09a5510cf77039a3b903e94e8922f25ed203d7 \ - --hash=sha256:7e48cdb8226644e2fbd0bdb0a0f87906a3db07087f4de77a1b1b1ccfd9e93685 \ - --hash=sha256:7f63d176a81555984e91f2c84c2a574a61cab7111cc907e176f0f01538e9ff6e \ - --hash=sha256:7f6595c852ca544aaeeb32d357e62c9c780eac69dcd34e40cae7b55bc4fb1147 \ - --hash=sha256:7fac95714b09da9278a0b52e492466f773cfe37651cf467a83a1b659be24bf71 \ - --hash=sha256:81713b70bea5c1386dc2f32a8f0dab4148a2928c7495c808c541ee0aae614d67 \ - --hash=sha256:846dd2e1243407133d3195d2d7e4ceefcaa5f5bf7278f0a9bda00967e6326b04 \ - --hash=sha256:84c063af19ef5130084db70ada40ce63a84f6c1ef4d3dbc34e5e8c4febb20822 \ - --hash=sha256:881764d610e3269964fc4bb3c19bb6fce55422828e152b885609ec176b41cf11 \ - --hash=sha256:8994b29c462de9a8fce2d591028b986dbbe1b32f3ad600b2d3e1c482c93abad6 \ - --hash=sha256:8c79e9d7e3d8a32d4824250a9c6401194fb4c2ad9a0cec8f6a96e09a582c2cc0 \ - --hash=sha256:8ee427208c675f1b6e344a1f89376a9613fc30b52646a04ac0c1f6587c7e46ec \ - --hash=sha256:949681f68e0e3c25377462be4b658500e85ca24323d9619fdc41f68d46a1ffda \ - --hash=sha256:9e275792097c9f7e80741c36de3b61917aebecc08a67ae62899b074566ff8556 \ - --hash=sha256:9fb815155aac6bfa8d86184079652c9715c812d506b22cfa369196ef4e99d1b4 \ - --hash=sha256:a2a64e62c7a0edd07c1c917b0586655f3362d2c2d37d474db1a509efb96fea1c \ - --hash=sha256:a7ac5b4984c468ce4f4a553df281450df0a34aefae02e58d77a0847be8d1e11f \ - --hash=sha256:aa46dce75078fceaf7cecac5817422febb4355fbdda440db55206e3bd288cfb8 \ - --hash=sha256:ae3476e934b9d714aa8000d2e4c01eb2590eee10b9d8cd03e7983ad65dfbfcba \ - --hash=sha256:b0341e6d9a0c0e3cdc65857ef518bb05b410dbd70d749a0d33ac0f39e81a4258 \ - --hash=sha256:b40d1bf6e6f74f7c0a567a9e5e778bbd4699d1d3d2c0fe46f4b717eef9e96b95 \ - --hash=sha256:b5c4804e4039f487e942c13381e6c27b4b4e66066d94ef1fae3f6ba8b953f383 \ - --hash=sha256:b5d6a6c9602fd4598fa07e0389e19fe199ae96449008d8304bf5d47cb745462e \ - --hash=sha256:b5f1ac7359e17efe0b6e5fec21de34145caef22b260e978336f325d5c84e6938 \ - --hash=sha256:c0167540094838ee9093ef6cc2c69d0074bbf84a432b4995835e8e5a0d984374 \ - --hash=sha256:c180ac742a083e109c1a18151f4dd8675f32679985a1c750d2ff806796165b55 \ - --hash=sha256:c73df5b6e8fabe2ddb74876fb82d9dd44cbace0ca12e8861ce9155ad3c886139 \ - --hash=sha256:c7e177c619342e407415d4f35dec63d2d134d951e24b5166afcdfd1362828e17 \ - --hash=sha256:cbad927ea8ed814622305d842c93412cb47bd39a496ed0f96bfd42b922b4a217 \ - --hash=sha256:cc353841428d56b683a123a813e6a686e07026d6b1c5757970a877195f880c2d \ - --hash=sha256:cc7c92c1baa629cb03ecb0c3d12564f172218fb1739f54bf5f3881844daadc6d \ - --hash=sha256:cc7d768260f4ba4ea01741c1b5fe3d3a6c70eb91c87f4c8761bbcce5181beafe \ - --hash=sha256:d0eea830b591dbc68e030c86a9569826145df485b2b4554874b07fea1275a199 \ - --hash=sha256:d216e5d9b8749563c7f2c6f7a0831057ec844c68b4c11cb10fc62d4fd373c26d \ - --hash=sha256:d401f07261dc5aa36c2e4efc308548f6ae943bfff20fcadb0a07517a26b196d8 \ - --hash=sha256:d6324274b4e0e2fa1b3eccb25997b1c9ed134ff61d296448ab8269f5ac068c4c \ - --hash=sha256:d8a8b74d843c2638f3864a17d97a4acda58e40d3e44b6303b8cc3d3c44ae2d29 \ - --hash=sha256:d9b6b28a57feb51605d6ae5e61a9044a31742db557a3b851a74c13bc61de5172 \ - --hash=sha256:de599af166970d6a61accde358ec9ded821234cbbc8c6413acfec06056b8e860 \ - --hash=sha256:e594b22688d5747b06e957f1ef822060cb5cb35b493066e33ceac0cf882188b7 \ - --hash=sha256:e5b078134f48552c4d9527db2f7da0b5359abd49393cdf9794017baec7506170 \ - --hash=sha256:eb6dce402734575e1a8cc0bb1509afca508a400a57ce13d306ea2c663bad1138 \ - --hash=sha256:f1790a4b1e8e8e028c391175433b9c8122c39b46e1663228158e61e6f915bf06 \ - --hash=sha256:f5efe0661b9fcd6246f27957f6ae1c0eb29bc60552820f01e970b4996e016004 \ - --hash=sha256:f9cbfbc5faca235fbdf531b93aa0f9f005ec7d267d9d738761a4d42b744ea159 \ - --hash=sha256:fbea1751729afe607d84acfd01efd95e3b31db148a181a441984ce9b3d3469da \ - --hash=sha256:fca4b4307ebe9c3ec77a084da3a9d1999d164693d16492ca2b64594340999988 \ - --hash=sha256:ff5c6771c7e3511a06555afa317879b7db8d640137ba55d6ab0d0c50425cab75 +yarl==1.17.2 ; python_full_version >= "3.11.0" and python_version < "3.14" \ + --hash=sha256:0c8e589379ef0407b10bed16cc26e7392ef8f86961a706ade0a22309a45414d7 \ + --hash=sha256:0d41c684f286ce41fa05ab6af70f32d6da1b6f0457459a56cf9e393c1c0b2217 \ + --hash=sha256:1056cadd5e850a1c026f28e0704ab0a94daaa8f887ece8dfed30f88befb87bb0 \ + --hash=sha256:11d86c6145ac5c706c53d484784cf504d7d10fa407cb73b9d20f09ff986059ef \ + --hash=sha256:170ed4971bf9058582b01a8338605f4d8c849bd88834061e60e83b52d0c76870 \ + --hash=sha256:17791acaa0c0f89323c57da7b9a79f2174e26d5debbc8c02d84ebd80c2b7bff8 \ + --hash=sha256:17931dfbb84ae18b287279c1f92b76a3abcd9a49cd69b92e946035cff06bcd20 \ + --hash=sha256:18662443c6c3707e2fc7fad184b4dc32dd428710bbe72e1bce7fe1988d4aa654 \ + --hash=sha256:187df91395c11e9f9dc69b38d12406df85aa5865f1766a47907b1cc9855b6303 \ + --hash=sha256:1fee66b32e79264f428dc8da18396ad59cc48eef3c9c13844adec890cd339db5 \ + --hash=sha256:2270d590997445a0dc29afa92e5534bfea76ba3aea026289e811bf9ed4b65a7f \ + --hash=sha256:2654caaf5584449d49c94a6b382b3cb4a246c090e72453493ea168b931206a4d \ + --hash=sha256:26bfb6226e0c157af5da16d2d62258f1ac578d2899130a50433ffee4a5dfa673 \ + --hash=sha256:2941756754a10e799e5b87e2319bbec481ed0957421fba0e7b9fb1c11e40509f \ + --hash=sha256:3294f787a437cb5d81846de3a6697f0c35ecff37a932d73b1fe62490bef69211 \ + --hash=sha256:358dc7ddf25e79e1cc8ee16d970c23faee84d532b873519c5036dbb858965795 \ + --hash=sha256:38bc4ed5cae853409cb193c87c86cd0bc8d3a70fd2268a9807217b9176093ac6 \ + --hash=sha256:3a0baff7827a632204060f48dca9e63fbd6a5a0b8790c1a2adfb25dc2c9c0d50 \ + --hash=sha256:3a3ede8c248f36b60227eb777eac1dbc2f1022dc4d741b177c4379ca8e75571a \ + --hash=sha256:3a58a2f2ca7aaf22b265388d40232f453f67a6def7355a840b98c2d547bd037f \ + --hash=sha256:4434b739a8a101a837caeaa0137e0e38cb4ea561f39cb8960f3b1e7f4967a3fc \ + --hash=sha256:460024cacfc3246cc4d9f47a7fc860e4fcea7d1dc651e1256510d8c3c9c7cde0 \ + --hash=sha256:46c465ad06971abcf46dd532f77560181387b4eea59084434bdff97524444032 \ + --hash=sha256:48e424347a45568413deec6f6ee2d720de2cc0385019bedf44cd93e8638aa0ed \ + --hash=sha256:4a8c83f6fcdc327783bdc737e8e45b2e909b7bd108c4da1892d3bc59c04a6d84 \ + --hash=sha256:4c840cc11163d3c01a9d8aad227683c48cd3e5be5a785921bcc2a8b4b758c4f3 \ + --hash=sha256:4d486ddcaca8c68455aa01cf53d28d413fb41a35afc9f6594a730c9779545876 \ + --hash=sha256:4e76381be3d8ff96a4e6c77815653063e87555981329cf8f85e5be5abf449021 \ + --hash=sha256:50d866f7b1a3f16f98603e095f24c0eeba25eb508c85a2c5939c8b3870ba2df8 \ + --hash=sha256:52492b87d5877ec405542f43cd3da80bdcb2d0c2fbc73236526e5f2c28e6db28 \ + --hash=sha256:56afb44a12b0864d17b597210d63a5b88915d680f6484d8d202ed68ade38673d \ + --hash=sha256:585ce7cd97be8f538345de47b279b879e091c8b86d9dbc6d98a96a7ad78876a3 \ + --hash=sha256:5870d620b23b956f72bafed6a0ba9a62edb5f2ef78a8849b7615bd9433384171 \ + --hash=sha256:5c6ea72fe619fee5e6b5d4040a451d45d8175f560b11b3d3e044cd24b2720526 \ + --hash=sha256:688058e89f512fb7541cb85c2f149c292d3fa22f981d5a5453b40c5da49eb9e8 \ + --hash=sha256:6a3f47930fbbed0f6377639503848134c4aa25426b08778d641491131351c2c8 \ + --hash=sha256:6b981316fcd940f085f646b822c2ff2b8b813cbd61281acad229ea3cbaabeb6b \ + --hash=sha256:734144cd2bd633a1516948e477ff6c835041c0536cef1d5b9a823ae29899665b \ + --hash=sha256:736bb076f7299c5c55dfef3eb9e96071a795cb08052822c2bb349b06f4cb2e0a \ + --hash=sha256:752485cbbb50c1e20908450ff4f94217acba9358ebdce0d8106510859d6eb19a \ + --hash=sha256:753eaaa0c7195244c84b5cc159dc8204b7fd99f716f11198f999f2332a86b178 \ + --hash=sha256:75ac158560dec3ed72f6d604c81090ec44529cfb8169b05ae6fcb3e986b325d9 \ + --hash=sha256:76499469dcc24759399accd85ec27f237d52dec300daaca46a5352fcbebb1071 \ + --hash=sha256:782ca9c58f5c491c7afa55518542b2b005caedaf4685ec814fadfcee51f02493 \ + --hash=sha256:792155279dc093839e43f85ff7b9b6493a8eaa0af1f94f1f9c6e8f4de8c63500 \ + --hash=sha256:7a1606ba68e311576bcb1672b2a1543417e7e0aa4c85e9e718ba6466952476c0 \ + --hash=sha256:8281db240a1616af2f9c5f71d355057e73a1409c4648c8949901396dc0a3c151 \ + --hash=sha256:871e1b47eec7b6df76b23c642a81db5dd6536cbef26b7e80e7c56c2fd371382e \ + --hash=sha256:8b9c4643e7d843a0dca9cd9d610a0876e90a1b2cbc4c5ba7930a0d90baf6903f \ + --hash=sha256:8c6d5fed96f0646bfdf698b0a1cebf32b8aae6892d1bec0c5d2d6e2df44e1e2d \ + --hash=sha256:8e1bf59e035534ba4077f5361d8d5d9194149f9ed4f823d1ee29ef3e8964ace3 \ + --hash=sha256:8fd51299e21da709eabcd5b2dd60e39090804431292daacbee8d3dabe39a6bc0 \ + --hash=sha256:91c012dceadc695ccf69301bfdccd1fc4472ad714fe2dd3c5ab4d2046afddf29 \ + --hash=sha256:93771146ef048b34201bfa382c2bf74c524980870bb278e6df515efaf93699ff \ + --hash=sha256:93d1c8cc5bf5df401015c5e2a3ce75a5254a9839e5039c881365d2a9dcfc6dc2 \ + --hash=sha256:9611b83810a74a46be88847e0ea616794c406dbcb4e25405e52bff8f4bee2d0a \ + --hash=sha256:9bc27dd5cfdbe3dc7f381b05e6260ca6da41931a6e582267d5ca540270afeeb2 \ + --hash=sha256:ac8eda86cc75859093e9ce390d423aba968f50cf0e481e6c7d7d63f90bae5c9c \ + --hash=sha256:bc3003710e335e3f842ae3fd78efa55f11a863a89a72e9a07da214db3bf7e1f8 \ + --hash=sha256:bc61b005f6521fcc00ca0d1243559a5850b9dd1e1fe07b891410ee8fe192d0c0 \ + --hash=sha256:be4c7b1c49d9917c6e95258d3d07f43cfba2c69a6929816e77daf322aaba6628 \ + --hash=sha256:c019abc2eca67dfa4d8fb72ba924871d764ec3c92b86d5b53b405ad3d6aa56b0 \ + --hash=sha256:c42774d1d1508ec48c3ed29e7b110e33f5e74a20957ea16197dbcce8be6b52ba \ + --hash=sha256:c556fbc6820b6e2cda1ca675c5fa5589cf188f8da6b33e9fc05b002e603e44fa \ + --hash=sha256:c6e659b9a24d145e271c2faf3fa6dd1fcb3e5d3f4e17273d9e0350b6ab0fe6e2 \ + --hash=sha256:c74f0b0472ac40b04e6d28532f55cac8090e34c3e81f118d12843e6df14d0909 \ + --hash=sha256:cd7e35818d2328b679a13268d9ea505c85cd773572ebb7a0da7ccbca77b6a52e \ + --hash=sha256:d17832ba39374134c10e82d137e372b5f7478c4cceeb19d02ae3e3d1daed8721 \ + --hash=sha256:d1fa68a3c921365c5745b4bd3af6221ae1f0ea1bf04b69e94eda60e57958907f \ + --hash=sha256:d63123bfd0dce5f91101e77c8a5427c3872501acece8c90df457b486bc1acd47 \ + --hash=sha256:da9d3061e61e5ae3f753654813bc1cd1c70e02fb72cf871bd6daf78443e9e2b1 \ + --hash=sha256:db5ac3871ed76340210fe028f535392f097fb31b875354bcb69162bba2632ef4 \ + --hash=sha256:dd7abf4f717e33b7487121faf23560b3a50924f80e4bef62b22dab441ded8f3b \ + --hash=sha256:dd90238d3a77a0e07d4d6ffdebc0c21a9787c5953a508a2231b5f191455f31e9 \ + --hash=sha256:ef6eee1a61638d29cd7c85f7fd3ac7b22b4c0fabc8fd00a712b727a3e73b0685 \ + --hash=sha256:f11fd61d72d93ac23718d393d2a64469af40be2116b24da0a4ca6922df26807e \ + --hash=sha256:f1e7fedb09c059efee2533119666ca7e1a2610072076926fa028c2ba5dfeb78c \ + --hash=sha256:f25b7e93f5414b9a983e1a6c1820142c13e1782cc9ed354c25e933aebe97fcf2 \ + --hash=sha256:f2f44a4247461965fed18b2573f3a9eb5e2c3cad225201ee858726cde610daca \ + --hash=sha256:f5ffc6b7ace5b22d9e73b2a4c7305740a339fbd55301d52735f73e21d9eb3130 \ + --hash=sha256:ff6af03cac0d1a4c3c19e5dcc4c05252411bf44ccaa2485e20d0a7c77892ab6e \ + --hash=sha256:ff8d95e06546c3a8c188f68040e9d0360feb67ba8498baf018918f669f7bc39b diff --git a/dev-requirements/type-checking.txt b/dev-requirements/type-checking.txt index 1b12f1153..b525533a1 100644 --- a/dev-requirements/type-checking.txt +++ b/dev-requirements/type-checking.txt @@ -558,86 +558,86 @@ typing-extensions==4.12.2 ; python_full_version >= "3.11.0" and python_version < virtualenv==20.27.1 ; python_full_version >= "3.11.0" and python_version < "3.14" \ --hash=sha256:142c6be10212543b32c6c45d3d3893dff89112cc588b7d0879ae5a1ec03a47ba \ --hash=sha256:f11f1b8a29525562925f745563bfd48b189450f61fb34c4f9cc79dd5aa32a1f4 -yarl==1.17.1 ; python_full_version >= "3.11.0" and python_version < "3.14" \ - --hash=sha256:06157fb3c58f2736a5e47c8fcbe1afc8b5de6fb28b14d25574af9e62150fcaac \ - --hash=sha256:067a63fcfda82da6b198fa73079b1ca40b7c9b7994995b6ee38acda728b64d47 \ - --hash=sha256:0b1794853124e2f663f0ea54efb0340b457f08d40a1cef78edfa086576179c91 \ - --hash=sha256:0bdff5e0995522706c53078f531fb586f56de9c4c81c243865dd5c66c132c3b5 \ - --hash=sha256:117ed8b3732528a1e41af3aa6d4e08483c2f0f2e3d3d7dca7cf538b3516d93df \ - --hash=sha256:14bc88baa44e1f84164a392827b5defb4fa8e56b93fecac3d15315e7c8e5d8b3 \ - --hash=sha256:1654ec814b18be1af2c857aa9000de7a601400bd4c9ca24629b18486c2e35463 \ - --hash=sha256:16bca6678a83657dd48df84b51bd56a6c6bd401853aef6d09dc2506a78484c7b \ - --hash=sha256:1a3b91c44efa29e6c8ef8a9a2b583347998e2ba52c5d8280dbd5919c02dfc3b5 \ - --hash=sha256:1a52a1ffdd824fb1835272e125385c32fd8b17fbdefeedcb4d543cc23b332d74 \ - --hash=sha256:1ce36ded585f45b1e9bb36d0ae94765c6608b43bd2e7f5f88079f7a85c61a4d3 \ - --hash=sha256:299f11b44d8d3a588234adbe01112126010bd96d9139c3ba7b3badd9829261c3 \ - --hash=sha256:2b24ec55fad43e476905eceaf14f41f6478780b870eda5d08b4d6de9a60b65b4 \ - --hash=sha256:2d374d70fdc36f5863b84e54775452f68639bc862918602d028f89310a034ab0 \ - --hash=sha256:2d9f0606baaec5dd54cb99667fcf85183a7477f3766fbddbe3f385e7fc253299 \ - --hash=sha256:2e7ba4c9377e48fb7b20dedbd473cbcbc13e72e1826917c185157a137dac9df2 \ - --hash=sha256:2f0a6423295a0d282d00e8701fe763eeefba8037e984ad5de44aa349002562ac \ - --hash=sha256:327828786da2006085a4d1feb2594de6f6d26f8af48b81eb1ae950c788d97f61 \ - --hash=sha256:380e6c38ef692b8fd5a0f6d1fa8774d81ebc08cfbd624b1bca62a4d4af2f9931 \ - --hash=sha256:3b74ff4767d3ef47ffe0cd1d89379dc4d828d4873e5528976ced3b44fe5b0a21 \ - --hash=sha256:3e844be8d536afa129366d9af76ed7cb8dfefec99f5f1c9e4f8ae542279a6dc3 \ - --hash=sha256:459e81c2fb920b5f5df744262d1498ec2c8081acdcfe18181da44c50f51312f7 \ - --hash=sha256:46ddf6e0b975cd680eb83318aa1d321cb2bf8d288d50f1754526230fcf59ba96 \ - --hash=sha256:482c122b72e3c5ec98f11457aeb436ae4aecca75de19b3d1de7cf88bc40db82f \ - --hash=sha256:561c87fea99545ef7d692403c110b2f99dced6dff93056d6e04384ad3bc46243 \ - --hash=sha256:578d00c9b7fccfa1745a44f4eddfdc99d723d157dad26764538fbdda37209857 \ - --hash=sha256:58c8e9620eb82a189c6c40cb6b59b4e35b2ee68b1f2afa6597732a2b467d7e8f \ - --hash=sha256:5b29beab10211a746f9846baa39275e80034e065460d99eb51e45c9a9495bcca \ - --hash=sha256:5d1d42556b063d579cae59e37a38c61f4402b47d70c29f0ef15cee1acaa64488 \ - --hash=sha256:5f236cb5999ccd23a0ab1bd219cfe0ee3e1c1b65aaf6dd3320e972f7ec3a39da \ - --hash=sha256:62a91aefff3d11bf60e5956d340eb507a983a7ec802b19072bb989ce120cd948 \ - --hash=sha256:64cc6e97f14cf8a275d79c5002281f3040c12e2e4220623b5759ea7f9868d6a5 \ - --hash=sha256:6f4c9156c4d1eb490fe374fb294deeb7bc7eaccda50e23775b2354b6a6739934 \ - --hash=sha256:7294e38f9aa2e9f05f765b28ffdc5d81378508ce6dadbe93f6d464a8c9594473 \ - --hash=sha256:7615058aabad54416ddac99ade09a5510cf77039a3b903e94e8922f25ed203d7 \ - --hash=sha256:7e48cdb8226644e2fbd0bdb0a0f87906a3db07087f4de77a1b1b1ccfd9e93685 \ - --hash=sha256:7f63d176a81555984e91f2c84c2a574a61cab7111cc907e176f0f01538e9ff6e \ - --hash=sha256:7f6595c852ca544aaeeb32d357e62c9c780eac69dcd34e40cae7b55bc4fb1147 \ - --hash=sha256:7fac95714b09da9278a0b52e492466f773cfe37651cf467a83a1b659be24bf71 \ - --hash=sha256:81713b70bea5c1386dc2f32a8f0dab4148a2928c7495c808c541ee0aae614d67 \ - --hash=sha256:846dd2e1243407133d3195d2d7e4ceefcaa5f5bf7278f0a9bda00967e6326b04 \ - --hash=sha256:84c063af19ef5130084db70ada40ce63a84f6c1ef4d3dbc34e5e8c4febb20822 \ - --hash=sha256:881764d610e3269964fc4bb3c19bb6fce55422828e152b885609ec176b41cf11 \ - --hash=sha256:8994b29c462de9a8fce2d591028b986dbbe1b32f3ad600b2d3e1c482c93abad6 \ - --hash=sha256:8c79e9d7e3d8a32d4824250a9c6401194fb4c2ad9a0cec8f6a96e09a582c2cc0 \ - --hash=sha256:8ee427208c675f1b6e344a1f89376a9613fc30b52646a04ac0c1f6587c7e46ec \ - --hash=sha256:949681f68e0e3c25377462be4b658500e85ca24323d9619fdc41f68d46a1ffda \ - --hash=sha256:9e275792097c9f7e80741c36de3b61917aebecc08a67ae62899b074566ff8556 \ - --hash=sha256:9fb815155aac6bfa8d86184079652c9715c812d506b22cfa369196ef4e99d1b4 \ - --hash=sha256:a2a64e62c7a0edd07c1c917b0586655f3362d2c2d37d474db1a509efb96fea1c \ - --hash=sha256:a7ac5b4984c468ce4f4a553df281450df0a34aefae02e58d77a0847be8d1e11f \ - --hash=sha256:aa46dce75078fceaf7cecac5817422febb4355fbdda440db55206e3bd288cfb8 \ - --hash=sha256:ae3476e934b9d714aa8000d2e4c01eb2590eee10b9d8cd03e7983ad65dfbfcba \ - --hash=sha256:b0341e6d9a0c0e3cdc65857ef518bb05b410dbd70d749a0d33ac0f39e81a4258 \ - --hash=sha256:b40d1bf6e6f74f7c0a567a9e5e778bbd4699d1d3d2c0fe46f4b717eef9e96b95 \ - --hash=sha256:b5c4804e4039f487e942c13381e6c27b4b4e66066d94ef1fae3f6ba8b953f383 \ - --hash=sha256:b5d6a6c9602fd4598fa07e0389e19fe199ae96449008d8304bf5d47cb745462e \ - --hash=sha256:b5f1ac7359e17efe0b6e5fec21de34145caef22b260e978336f325d5c84e6938 \ - --hash=sha256:c0167540094838ee9093ef6cc2c69d0074bbf84a432b4995835e8e5a0d984374 \ - --hash=sha256:c180ac742a083e109c1a18151f4dd8675f32679985a1c750d2ff806796165b55 \ - --hash=sha256:c73df5b6e8fabe2ddb74876fb82d9dd44cbace0ca12e8861ce9155ad3c886139 \ - --hash=sha256:c7e177c619342e407415d4f35dec63d2d134d951e24b5166afcdfd1362828e17 \ - --hash=sha256:cbad927ea8ed814622305d842c93412cb47bd39a496ed0f96bfd42b922b4a217 \ - --hash=sha256:cc353841428d56b683a123a813e6a686e07026d6b1c5757970a877195f880c2d \ - --hash=sha256:cc7c92c1baa629cb03ecb0c3d12564f172218fb1739f54bf5f3881844daadc6d \ - --hash=sha256:cc7d768260f4ba4ea01741c1b5fe3d3a6c70eb91c87f4c8761bbcce5181beafe \ - --hash=sha256:d0eea830b591dbc68e030c86a9569826145df485b2b4554874b07fea1275a199 \ - --hash=sha256:d216e5d9b8749563c7f2c6f7a0831057ec844c68b4c11cb10fc62d4fd373c26d \ - --hash=sha256:d401f07261dc5aa36c2e4efc308548f6ae943bfff20fcadb0a07517a26b196d8 \ - --hash=sha256:d6324274b4e0e2fa1b3eccb25997b1c9ed134ff61d296448ab8269f5ac068c4c \ - --hash=sha256:d8a8b74d843c2638f3864a17d97a4acda58e40d3e44b6303b8cc3d3c44ae2d29 \ - --hash=sha256:d9b6b28a57feb51605d6ae5e61a9044a31742db557a3b851a74c13bc61de5172 \ - --hash=sha256:de599af166970d6a61accde358ec9ded821234cbbc8c6413acfec06056b8e860 \ - --hash=sha256:e594b22688d5747b06e957f1ef822060cb5cb35b493066e33ceac0cf882188b7 \ - --hash=sha256:e5b078134f48552c4d9527db2f7da0b5359abd49393cdf9794017baec7506170 \ - --hash=sha256:eb6dce402734575e1a8cc0bb1509afca508a400a57ce13d306ea2c663bad1138 \ - --hash=sha256:f1790a4b1e8e8e028c391175433b9c8122c39b46e1663228158e61e6f915bf06 \ - --hash=sha256:f5efe0661b9fcd6246f27957f6ae1c0eb29bc60552820f01e970b4996e016004 \ - --hash=sha256:f9cbfbc5faca235fbdf531b93aa0f9f005ec7d267d9d738761a4d42b744ea159 \ - --hash=sha256:fbea1751729afe607d84acfd01efd95e3b31db148a181a441984ce9b3d3469da \ - --hash=sha256:fca4b4307ebe9c3ec77a084da3a9d1999d164693d16492ca2b64594340999988 \ - --hash=sha256:ff5c6771c7e3511a06555afa317879b7db8d640137ba55d6ab0d0c50425cab75 +yarl==1.17.2 ; python_full_version >= "3.11.0" and python_version < "3.14" \ + --hash=sha256:0c8e589379ef0407b10bed16cc26e7392ef8f86961a706ade0a22309a45414d7 \ + --hash=sha256:0d41c684f286ce41fa05ab6af70f32d6da1b6f0457459a56cf9e393c1c0b2217 \ + --hash=sha256:1056cadd5e850a1c026f28e0704ab0a94daaa8f887ece8dfed30f88befb87bb0 \ + --hash=sha256:11d86c6145ac5c706c53d484784cf504d7d10fa407cb73b9d20f09ff986059ef \ + --hash=sha256:170ed4971bf9058582b01a8338605f4d8c849bd88834061e60e83b52d0c76870 \ + --hash=sha256:17791acaa0c0f89323c57da7b9a79f2174e26d5debbc8c02d84ebd80c2b7bff8 \ + --hash=sha256:17931dfbb84ae18b287279c1f92b76a3abcd9a49cd69b92e946035cff06bcd20 \ + --hash=sha256:18662443c6c3707e2fc7fad184b4dc32dd428710bbe72e1bce7fe1988d4aa654 \ + --hash=sha256:187df91395c11e9f9dc69b38d12406df85aa5865f1766a47907b1cc9855b6303 \ + --hash=sha256:1fee66b32e79264f428dc8da18396ad59cc48eef3c9c13844adec890cd339db5 \ + --hash=sha256:2270d590997445a0dc29afa92e5534bfea76ba3aea026289e811bf9ed4b65a7f \ + --hash=sha256:2654caaf5584449d49c94a6b382b3cb4a246c090e72453493ea168b931206a4d \ + --hash=sha256:26bfb6226e0c157af5da16d2d62258f1ac578d2899130a50433ffee4a5dfa673 \ + --hash=sha256:2941756754a10e799e5b87e2319bbec481ed0957421fba0e7b9fb1c11e40509f \ + --hash=sha256:3294f787a437cb5d81846de3a6697f0c35ecff37a932d73b1fe62490bef69211 \ + --hash=sha256:358dc7ddf25e79e1cc8ee16d970c23faee84d532b873519c5036dbb858965795 \ + --hash=sha256:38bc4ed5cae853409cb193c87c86cd0bc8d3a70fd2268a9807217b9176093ac6 \ + --hash=sha256:3a0baff7827a632204060f48dca9e63fbd6a5a0b8790c1a2adfb25dc2c9c0d50 \ + --hash=sha256:3a3ede8c248f36b60227eb777eac1dbc2f1022dc4d741b177c4379ca8e75571a \ + --hash=sha256:3a58a2f2ca7aaf22b265388d40232f453f67a6def7355a840b98c2d547bd037f \ + --hash=sha256:4434b739a8a101a837caeaa0137e0e38cb4ea561f39cb8960f3b1e7f4967a3fc \ + --hash=sha256:460024cacfc3246cc4d9f47a7fc860e4fcea7d1dc651e1256510d8c3c9c7cde0 \ + --hash=sha256:46c465ad06971abcf46dd532f77560181387b4eea59084434bdff97524444032 \ + --hash=sha256:48e424347a45568413deec6f6ee2d720de2cc0385019bedf44cd93e8638aa0ed \ + --hash=sha256:4a8c83f6fcdc327783bdc737e8e45b2e909b7bd108c4da1892d3bc59c04a6d84 \ + --hash=sha256:4c840cc11163d3c01a9d8aad227683c48cd3e5be5a785921bcc2a8b4b758c4f3 \ + --hash=sha256:4d486ddcaca8c68455aa01cf53d28d413fb41a35afc9f6594a730c9779545876 \ + --hash=sha256:4e76381be3d8ff96a4e6c77815653063e87555981329cf8f85e5be5abf449021 \ + --hash=sha256:50d866f7b1a3f16f98603e095f24c0eeba25eb508c85a2c5939c8b3870ba2df8 \ + --hash=sha256:52492b87d5877ec405542f43cd3da80bdcb2d0c2fbc73236526e5f2c28e6db28 \ + --hash=sha256:56afb44a12b0864d17b597210d63a5b88915d680f6484d8d202ed68ade38673d \ + --hash=sha256:585ce7cd97be8f538345de47b279b879e091c8b86d9dbc6d98a96a7ad78876a3 \ + --hash=sha256:5870d620b23b956f72bafed6a0ba9a62edb5f2ef78a8849b7615bd9433384171 \ + --hash=sha256:5c6ea72fe619fee5e6b5d4040a451d45d8175f560b11b3d3e044cd24b2720526 \ + --hash=sha256:688058e89f512fb7541cb85c2f149c292d3fa22f981d5a5453b40c5da49eb9e8 \ + --hash=sha256:6a3f47930fbbed0f6377639503848134c4aa25426b08778d641491131351c2c8 \ + --hash=sha256:6b981316fcd940f085f646b822c2ff2b8b813cbd61281acad229ea3cbaabeb6b \ + --hash=sha256:734144cd2bd633a1516948e477ff6c835041c0536cef1d5b9a823ae29899665b \ + --hash=sha256:736bb076f7299c5c55dfef3eb9e96071a795cb08052822c2bb349b06f4cb2e0a \ + --hash=sha256:752485cbbb50c1e20908450ff4f94217acba9358ebdce0d8106510859d6eb19a \ + --hash=sha256:753eaaa0c7195244c84b5cc159dc8204b7fd99f716f11198f999f2332a86b178 \ + --hash=sha256:75ac158560dec3ed72f6d604c81090ec44529cfb8169b05ae6fcb3e986b325d9 \ + --hash=sha256:76499469dcc24759399accd85ec27f237d52dec300daaca46a5352fcbebb1071 \ + --hash=sha256:782ca9c58f5c491c7afa55518542b2b005caedaf4685ec814fadfcee51f02493 \ + --hash=sha256:792155279dc093839e43f85ff7b9b6493a8eaa0af1f94f1f9c6e8f4de8c63500 \ + --hash=sha256:7a1606ba68e311576bcb1672b2a1543417e7e0aa4c85e9e718ba6466952476c0 \ + --hash=sha256:8281db240a1616af2f9c5f71d355057e73a1409c4648c8949901396dc0a3c151 \ + --hash=sha256:871e1b47eec7b6df76b23c642a81db5dd6536cbef26b7e80e7c56c2fd371382e \ + --hash=sha256:8b9c4643e7d843a0dca9cd9d610a0876e90a1b2cbc4c5ba7930a0d90baf6903f \ + --hash=sha256:8c6d5fed96f0646bfdf698b0a1cebf32b8aae6892d1bec0c5d2d6e2df44e1e2d \ + --hash=sha256:8e1bf59e035534ba4077f5361d8d5d9194149f9ed4f823d1ee29ef3e8964ace3 \ + --hash=sha256:8fd51299e21da709eabcd5b2dd60e39090804431292daacbee8d3dabe39a6bc0 \ + --hash=sha256:91c012dceadc695ccf69301bfdccd1fc4472ad714fe2dd3c5ab4d2046afddf29 \ + --hash=sha256:93771146ef048b34201bfa382c2bf74c524980870bb278e6df515efaf93699ff \ + --hash=sha256:93d1c8cc5bf5df401015c5e2a3ce75a5254a9839e5039c881365d2a9dcfc6dc2 \ + --hash=sha256:9611b83810a74a46be88847e0ea616794c406dbcb4e25405e52bff8f4bee2d0a \ + --hash=sha256:9bc27dd5cfdbe3dc7f381b05e6260ca6da41931a6e582267d5ca540270afeeb2 \ + --hash=sha256:ac8eda86cc75859093e9ce390d423aba968f50cf0e481e6c7d7d63f90bae5c9c \ + --hash=sha256:bc3003710e335e3f842ae3fd78efa55f11a863a89a72e9a07da214db3bf7e1f8 \ + --hash=sha256:bc61b005f6521fcc00ca0d1243559a5850b9dd1e1fe07b891410ee8fe192d0c0 \ + --hash=sha256:be4c7b1c49d9917c6e95258d3d07f43cfba2c69a6929816e77daf322aaba6628 \ + --hash=sha256:c019abc2eca67dfa4d8fb72ba924871d764ec3c92b86d5b53b405ad3d6aa56b0 \ + --hash=sha256:c42774d1d1508ec48c3ed29e7b110e33f5e74a20957ea16197dbcce8be6b52ba \ + --hash=sha256:c556fbc6820b6e2cda1ca675c5fa5589cf188f8da6b33e9fc05b002e603e44fa \ + --hash=sha256:c6e659b9a24d145e271c2faf3fa6dd1fcb3e5d3f4e17273d9e0350b6ab0fe6e2 \ + --hash=sha256:c74f0b0472ac40b04e6d28532f55cac8090e34c3e81f118d12843e6df14d0909 \ + --hash=sha256:cd7e35818d2328b679a13268d9ea505c85cd773572ebb7a0da7ccbca77b6a52e \ + --hash=sha256:d17832ba39374134c10e82d137e372b5f7478c4cceeb19d02ae3e3d1daed8721 \ + --hash=sha256:d1fa68a3c921365c5745b4bd3af6221ae1f0ea1bf04b69e94eda60e57958907f \ + --hash=sha256:d63123bfd0dce5f91101e77c8a5427c3872501acece8c90df457b486bc1acd47 \ + --hash=sha256:da9d3061e61e5ae3f753654813bc1cd1c70e02fb72cf871bd6daf78443e9e2b1 \ + --hash=sha256:db5ac3871ed76340210fe028f535392f097fb31b875354bcb69162bba2632ef4 \ + --hash=sha256:dd7abf4f717e33b7487121faf23560b3a50924f80e4bef62b22dab441ded8f3b \ + --hash=sha256:dd90238d3a77a0e07d4d6ffdebc0c21a9787c5953a508a2231b5f191455f31e9 \ + --hash=sha256:ef6eee1a61638d29cd7c85f7fd3ac7b22b4c0fabc8fd00a712b727a3e73b0685 \ + --hash=sha256:f11fd61d72d93ac23718d393d2a64469af40be2116b24da0a4ca6922df26807e \ + --hash=sha256:f1e7fedb09c059efee2533119666ca7e1a2610072076926fa028c2ba5dfeb78c \ + --hash=sha256:f25b7e93f5414b9a983e1a6c1820142c13e1782cc9ed354c25e933aebe97fcf2 \ + --hash=sha256:f2f44a4247461965fed18b2573f3a9eb5e2c3cad225201ee858726cde610daca \ + --hash=sha256:f5ffc6b7ace5b22d9e73b2a4c7305740a339fbd55301d52735f73e21d9eb3130 \ + --hash=sha256:ff6af03cac0d1a4c3c19e5dcc4c05252411bf44ccaa2485e20d0a7c77892ab6e \ + --hash=sha256:ff8d95e06546c3a8c188f68040e9d0360feb67ba8498baf018918f669f7bc39b From 1ae6a158eb9b26e21866a2900dc9f26e57a31c3a Mon Sep 17 00:00:00 2001 From: Faster Speeding Date: Sun, 17 Nov 2024 18:42:49 +0000 Subject: [PATCH 13/14] Ignore abc falke8 error --- pyproject.toml | 1 + 1 file changed, 1 insertion(+) diff --git a/pyproject.toml b/pyproject.toml index 89ac710d7..8c3607c8f 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -111,6 +111,7 @@ per-file-ignores = [ "docs_src/*.py: ASYNC102, ASYNC910, ASYNC911, DALL000, D100, D101, D103, E800, FA100, FA101, F841, INP001, N806, TC001, TC101", "examples/*.py: ASYNC102, ASYNC910, ASYNC911, DALL000, D100, D101, D103, E800, FA100, FA101, F401, F403, INP001, TC001, TC003", "noxfile.py: ASYNC102, ASYNC910, ASYNC911, D100, FA101, F401, F403, INP001", + "tanjun/abc.py: A005", # A005 the module is shadowing a Python builtin module "abc" "tanjun/py.typed: ASYNC102, ASYNC910, ASYNC911, D100", "tests/*.py: ASYNC102, ASYNC910, ASYNC911, CCE002, DALL000, D100, D101, D103, D104, FA100, FA101, TC003", "tests/test_annotations*.py: ASYNC102, ASYNC910, ASYNC911, CCE002, DALL000, D100, D101, D103, D104, FA100, FA101, TC101, TC003", From 372ede7628a8d44930be356ccce480e145664a7f Mon Sep 17 00:00:00 2001 From: Faster Speeding Date: Sun, 17 Nov 2024 19:04:24 +0000 Subject: [PATCH 14/14] Small fixes --- tanjun/checks.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tanjun/checks.py b/tanjun/checks.py index a0c23e872..1d6a2eb3d 100644 --- a/tanjun/checks.py +++ b/tanjun/checks.py @@ -1032,7 +1032,7 @@ def all_checks( Returns ------- - collections.abc.Callable[[tanjun.abc.Context], collections.Coroutine[typing.Any, typing.Any, bool]] + collections.abc.Callable[[tanjun.abc.Context], collections.abc.Coroutine[typing.Any, typing.Any, bool]] A check which will pass if all of the provided check callbacks pass. """ return _AllChecks[_ContextT]([check, *checks])