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..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.9", "3.10", "3.11", "3.12", "3.13-dev"]
+ python-version: ["3.11", "3.12", "3.13"]
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/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: |
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: |
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 b7e1c1eee..1557516ce 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 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,8 +64,8 @@ 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`.
-* Since this project supports python 3.9+, the `typing` types which were deprecated by
+ imports the typing module itself to use generics and types in it like `typing.Annotated`.
+* 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/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
diff --git a/dev-requirements/constraints.txt b/dev-requirements/constraints.txt
index 6826bbd68..ed1d7b2c8 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,89 +390,89 @@ 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" \
- --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.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/dev-requirements/tests.txt b/dev-requirements/tests.txt
index b3add1991..d21845d65 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,16 @@ 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" \
- --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 +363,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,119 +468,116 @@ 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" \
- --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 ad3069a6f..b525533a1 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,16 @@ 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" \
- --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 +372,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 +408,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,218 +522,122 @@ 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" \
- --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/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/piped b/piped
index 094e66ddc..8d5f6d318 160000
--- a/piped
+++ b/piped
@@ -1 +1 @@
-Subproject commit 094e66ddc94ec6e08802a4ce82b480eb368b9052
+Subproject commit 8d5f6d3185b78560ad285aeb9ad7c38f7c65c979
diff --git a/pyproject.toml b/pyproject.toml
index f72f9afe5..8c3607c8f 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",
@@ -41,11 +39,10 @@ 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
-target-version = ["py39"]
+target-version = ["py311"]
[tool.codespell]
ignore-regex = "TimeSchedule|Nd"
@@ -66,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"
@@ -81,7 +76,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
@@ -116,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",
@@ -126,11 +122,10 @@ per-file-ignores = [
[tool.isort]
profile = "black"
force_single_line = true
-skip = ["tanjun/_internal/vendor"]
[tool.mypy]
# some good strict settings
-python_version = 3.9
+python_version = "3.11"
strict = true
warn_unreachable = true
@@ -145,9 +140,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",
@@ -160,7 +152,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"]
@@ -170,7 +161,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"]
[tool.piped.github_actions.reformat]
[tool.piped.github_actions.release_docs]
@@ -185,10 +176,9 @@ python_versions = ["3.9", "3.10", "3.11", "3.12", "3.13-dev"]
exclude = "docs_src"
[tool.pyright]
-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.
@@ -235,4 +225,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..1d6a2eb3d 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
@@ -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..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
@@ -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..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
@@ -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..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
@@ -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..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
@@ -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_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 3cba50530..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
@@ -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_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 59584e11a..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
@@ -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..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
@@ -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___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 46b8c9128..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
@@ -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..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
@@ -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_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 91a1f4c21..d71c65d60 100644
--- a/tests/dependencies/test_owners.py
+++ b/tests/dependencies/test_owners.py
@@ -35,10 +35,9 @@
import asyncio
import datetime
import time
-import typing
+from unittest import mock
import hikari
-import mock
import pytest
import tanjun
@@ -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__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_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..32b5e3bf1 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())
@@ -3125,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
@@ -3179,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
@@ -3217,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
@@ -3259,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
@@ -3314,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
@@ -3357,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
@@ -3442,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
@@ -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: