mirror of
https://github.com/python-telegram-bot/python-telegram-bot.git
synced 2026-06-19 15:45:13 +00:00
Compare commits
535 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| 9ebd48903b | |||
| 1cf000c806 | |||
| 150328799a | |||
| 6d7134608f | |||
| 8266870ed7 | |||
| 519dee7e0c | |||
| 753f3727aa | |||
| 892a66d0e8 | |||
| d5e5874f96 | |||
| a5dacab8a9 | |||
| 76d8eaf0f2 | |||
| 1e4f31f1bb | |||
| 3464f24129 | |||
| 9323caf2b8 | |||
| 77c25931a9 | |||
| b75948ede4 | |||
| b0d22acedb | |||
| 35a48f82f4 | |||
| 5d73132838 | |||
| 7c23087d08 | |||
| 2d5f4a68bb | |||
| f9f1533c40 | |||
| dfb0ae3747 | |||
| 64006aa7ae | |||
| 69ddc47a6e | |||
| a2150b3751 | |||
| 79acc1ae53 | |||
| 4cdb1a0cf7 | |||
| 6319f4bae1 | |||
| d7e063dbad | |||
| 5dd7b8f1e2 | |||
| 61b87ba318 | |||
| dd592cdd7c | |||
| f57dd52100 | |||
| 16605c54d7 | |||
| e4b0f8cb64 | |||
| f2dc0175cd | |||
| a781a4fddb | |||
| 679d038979 | |||
| d0a6e5141c | |||
| 5f35304e63 | |||
| 3fc50c78eb | |||
| 3c9bba63eb | |||
| a9a7b07b10 | |||
| e1e7b621f1 | |||
| dfb3c13d1d | |||
| f7a3f67a9f | |||
| a6cd9c5292 | |||
| df20e49db1 | |||
| 4f255b6e21 | |||
| 4afe174b5c | |||
| 2ac52018c2 | |||
| ca7a30963d | |||
| c42a230b96 | |||
| ce9742a602 | |||
| 43279543a3 | |||
| eda2172617 | |||
| 89dfa37dbf | |||
| 3709c2fa93 | |||
| da93fe94ae | |||
| cec34e4bca | |||
| ffe23be992 | |||
| ef1685c436 | |||
| 151123745e | |||
| 0eb11ff3e9 | |||
| dab75fb963 | |||
| 62f89758d7 | |||
| 7a8f4412b2 | |||
| 032a859149 | |||
| 507d6bc0e3 | |||
| bd6a60bb30 | |||
| 3c8f6ed42b | |||
| 6540f288f5 | |||
| 5ab82a9c2b | |||
| 847b97f86e | |||
| efacc3dd1b | |||
| 2ce687c8f1 | |||
| a39a59ee9b | |||
| 06854633ab | |||
| 9a8b208ef7 | |||
| 2f06902518 | |||
| 2bc65560eb | |||
| 79e589b39e | |||
| bd3cdbcdbd | |||
| 9709c03b35 | |||
| 3409f51107 | |||
| 2eae2830f3 | |||
| 28d19c3b9a | |||
| e314e78d06 | |||
| 67a97ae5a7 | |||
| 9248c539d0 | |||
| 6b5e46cc08 | |||
| b3155b2e55 | |||
| ec909e62cf | |||
| 1223e851c3 | |||
| 0b352b043e | |||
| b9d2efdec5 | |||
| 8c692d1008 | |||
| 970d2ab085 | |||
| 60b439ff42 | |||
| b17b0d248d | |||
| e0f36867cc | |||
| 01f689373c | |||
| 1e05381133 | |||
| a05362c79a | |||
| fbf07bf126 | |||
| 3017bf00a4 | |||
| 374875c786 | |||
| 8f9db63f4f | |||
| 1787586902 | |||
| 9c50a38512 | |||
| 3a49372591 | |||
| e637d1733c | |||
| b89f5d6126 | |||
| 6578c76068 | |||
| a967dbe37a | |||
| af76a8485f | |||
| 8a205b10c0 | |||
| 6d70c56159 | |||
| 0913b859d7 | |||
| c3f17bb18e | |||
| 006a290b7b | |||
| 422993b8ab | |||
| 2ac4e009d0 | |||
| efe1392e73 | |||
| 0a673e8f7e | |||
| 86c8cae40d | |||
| f737702544 | |||
| 06f1da576e | |||
| 7a470d57c8 | |||
| 1714bfd8f6 | |||
| 71e4015e22 | |||
| 52237cf00c | |||
| dba7866aab | |||
| 98bed6f01a | |||
| 42d7c8c477 | |||
| 8018e5ff3f | |||
| c39839b026 | |||
| 4213c12c5b | |||
| 97226b1ae3 | |||
| 146ec54a00 | |||
| df8aae0a38 | |||
| 4ccc80f9c1 | |||
| cfc75bb08b | |||
| 51ef571a07 | |||
| 9ce0f49882 | |||
| 5b1e7399a4 | |||
| a83046e1ec | |||
| 44e8292838 | |||
| a9f6afd015 | |||
| 78c945d485 | |||
| 9e70ac8b7a | |||
| cf728496e4 | |||
| 078d775250 | |||
| 57298aa076 | |||
| 2c299bb109 | |||
| c1c5438f37 | |||
| 6ba7a097f4 | |||
| 6fc45a803d | |||
| 512a0b7417 | |||
| 7d952d8707 | |||
| b496fabf62 | |||
| 637b8e260b | |||
| 912fe45d8c | |||
| 805b7bff32 | |||
| f3bd0f1462 | |||
| 5b0e0b5f78 | |||
| c4623c4476 | |||
| ee6e82d7ad | |||
| c34f4811ea | |||
| d768abdd6b | |||
| 2561ffd16b | |||
| 622fdf7fa3 | |||
| 615f1bf20b | |||
| 7a8b1be5a4 | |||
| 3a8ace2e8b | |||
| 169bd47de3 | |||
| a956dcc6a4 | |||
| ee88973fee | |||
| 8f9fc65be0 | |||
| 75d946e4be | |||
| fed8d8875e | |||
| 42b68f1a70 | |||
| 58b8ef4ce4 | |||
| f6d009d3ac | |||
| 153894728c | |||
| 5fa457974d | |||
| 3ec7bb819c | |||
| 040cd2c2fc | |||
| 474f9c9693 | |||
| e18ca0d5e1 | |||
| 7331fff3fc | |||
| 23536ee759 | |||
| 2d8d43f2a5 | |||
| 8a542e22a0 | |||
| c0716dd344 | |||
| 668b49b048 | |||
| 22eb434a62 | |||
| ae2858783a | |||
| 2c227d5977 | |||
| 437261f716 | |||
| 1b98e440fa | |||
| d30ba3d1ef | |||
| 20e0f87f6b | |||
| bd9b0bd126 | |||
| 5d11d7fd42 | |||
| 099ab5d9fa | |||
| 26f943771b | |||
| 9c263fbd1a | |||
| 277031cfb2 | |||
| c513d51147 | |||
| bb6c85609a | |||
| 5b6cd3a33b | |||
| 1cf63c26c5 | |||
| 680dc2b6b8 | |||
| 04d86deb58 | |||
| 03d2359061 | |||
| 29866e2139 | |||
| 7e9537ece2 | |||
| baa01596c3 | |||
| c23eb8ec08 | |||
| 6ae7add722 | |||
| f3bda29e51 | |||
| fe0421a822 | |||
| 0325a024d6 | |||
| 2f65fcc292 | |||
| 2d63c57ed6 | |||
| b73dc5728e | |||
| f452c132fa | |||
| ebf7f3be12 | |||
| dc284a1a73 | |||
| 979988add1 | |||
| 1ae759ff5c | |||
| 1ab91370ac | |||
| 29d073871a | |||
| d03b4ec688 | |||
| 07d9dc7a44 | |||
| f3479cd170 | |||
| 7fcfad41a5 | |||
| c33c541cbe | |||
| 57c2f6e01e | |||
| a52c91996e | |||
| 2345bfbb53 | |||
| cc45f49a4f | |||
| fd6a0fe899 | |||
| 67b0706116 | |||
| 592c6cc6d3 | |||
| 1fc46360ff | |||
| 4ad94cc7f7 | |||
| c6a9fbb5c7 | |||
| af8729769b | |||
| f93f827e33 | |||
| a8f1164b0c | |||
| da11561f87 | |||
| 354a8e0854 | |||
| bc68488c14 | |||
| 19d7939355 | |||
| 3495ce3aeb | |||
| dd9af64a5c | |||
| da3bc6974a | |||
| b1fc0596b9 | |||
| 6d2334c88b | |||
| a0c81ec3d4 | |||
| c8d9898eaa | |||
| 616b0b55ef | |||
| c71612ffae | |||
| 4143d99f56 | |||
| cbe808e471 | |||
| 300ec920a1 | |||
| 075f517458 | |||
| c82a0808d1 | |||
| ea7e5a69aa | |||
| f67e8c0804 | |||
| af130ef5e7 | |||
| 9ef8826f33 | |||
| 61b70efb4c | |||
| 63977ea353 | |||
| ae57d3b7c3 | |||
| 8d76087bed | |||
| 0e90deafb5 | |||
| 39d45124df | |||
| 895403a0b5 | |||
| 8cb177cb2c | |||
| eaf802e07d | |||
| 1ef242a17e | |||
| 7adb4fa2db | |||
| 5c5ee598a2 | |||
| a4ae6f2097 | |||
| fc5a56c15b | |||
| 74112bfd06 | |||
| ab90cd7359 | |||
| 5b0f1697f1 | |||
| 9c7298c17a | |||
| 39abf838fa | |||
| 04b44f4595 | |||
| a0decdac28 | |||
| f77f4b0cf7 | |||
| 82c98b64a7 | |||
| f9ccf560f6 | |||
| 40ab8aadca | |||
| 644d76b592 | |||
| bd24da29cd | |||
| caffb9d66e | |||
| 1efd8e80ab | |||
| 8cc55c3381 | |||
| fbe9eeeaf5 | |||
| ebed8ec7d3 | |||
| 009785f028 | |||
| 7c858473ca | |||
| 58a109aae6 | |||
| 71eff4731c | |||
| c2c8c53d9c | |||
| 3b78934a77 | |||
| 5128748092 | |||
| 03f87750d4 | |||
| 4c4bf2185d | |||
| aaadc70fcc | |||
| ed3acd4b81 | |||
| a00ba52114 | |||
| 0ae991c141 | |||
| 7226aaea04 | |||
| 50a16edb41 | |||
| 59105b240f | |||
| db6030ea83 | |||
| 7d52ead228 | |||
| 589047ddbf | |||
| 5534ddfaa0 | |||
| 1d27a0fadb | |||
| 79cda7582e | |||
| dccf62eb1c | |||
| fb86bb3417 | |||
| 58b89cf0e9 | |||
| 4a6e0fd7a6 | |||
| 623d2f7f0b | |||
| 62a8cfc395 | |||
| b0cff31fc1 | |||
| 3c87e450fb | |||
| 8e91a6adba | |||
| 63fd846233 | |||
| 814c72052f | |||
| 1a7edd7a5d | |||
| f0e71216fe | |||
| ca37219a68 | |||
| c9636726f7 | |||
| 9c8d6efe7a | |||
| bf54599618 | |||
| 4c8d7332db | |||
| c185137c9e | |||
| 3c5a16be1c | |||
| cd25964419 | |||
| 5309cf6555 | |||
| bb8b508a22 | |||
| 4f15a7feee | |||
| 57c780c62f | |||
| 99fd4432db | |||
| e432c296a9 | |||
| 1fdccd7bf9 | |||
| bfbf6d3f94 | |||
| 0c4180c74b | |||
| 1c6ae435bf | |||
| 66b6d3c497 | |||
| 8c252c9822 | |||
| 450dc2115c | |||
| 87a6890900 | |||
| 83ab12c387 | |||
| 3f444dad8d | |||
| f23315d08b | |||
| 7b116be344 | |||
| 934e4c9bd4 | |||
| 1966fb25c5 | |||
| a333d8514a | |||
| b146c7131e | |||
| 53093ebceb | |||
| 401b2decce | |||
| 83a164e5ef | |||
| d91bc45cdc | |||
| 8967912f46 | |||
| 7ab2cafbee | |||
| 7e0ed2235e | |||
| 53abb7b4bd | |||
| 11f86b8813 | |||
| 9997a9f47e | |||
| 4aedb33d37 | |||
| 4ddc36c625 | |||
| 311f88a716 | |||
| 179cb49dbc | |||
| 512e390738 | |||
| 33b677aeb4 | |||
| 800598ced4 | |||
| ec20f27a82 | |||
| cd59c1c075 | |||
| 52b0f2c3c9 | |||
| 598f44f4c2 | |||
| 22d0dd1301 | |||
| c6b6b0a370 | |||
| ee6c8a5995 | |||
| d5a1a48145 | |||
| 963edbf191 | |||
| 43c3c8f568 | |||
| 49ea8d39fb | |||
| 7e86e8be14 | |||
| 5cff9adb55 | |||
| 217a5f929e | |||
| 007f432ee4 | |||
| 23a685335b | |||
| 9953216980 | |||
| bacdeb37fd | |||
| a0f98b241e | |||
| 23d0bd8fe3 | |||
| 1701950a1d | |||
| 851f7ff0b3 | |||
| 359232e6c7 | |||
| 9782510779 | |||
| deb6cb19b3 | |||
| 21ebdbc973 | |||
| 54d0294f92 | |||
| 5693add136 | |||
| 3dd7d84fa5 | |||
| 4ebcec2b91 | |||
| 200b623263 | |||
| c64bd7a715 | |||
| bbb9fcaaa5 | |||
| d48fa71ec5 | |||
| f9cbddd10a | |||
| 2797d9d305 | |||
| 19302bce25 | |||
| 3507cb13e6 | |||
| 6b59365464 | |||
| 74da17153b | |||
| 97e6e7e206 | |||
| d1159cd5ac | |||
| 51ad4d76d0 | |||
| 171953f109 | |||
| 606773d8f0 | |||
| f408b1a2dd | |||
| 3e7ab7e7af | |||
| 456b81d22a | |||
| cb90814829 | |||
| 7b61a30fb1 | |||
| f3a9b74445 | |||
| d996e8f9c9 | |||
| 0a6725852f | |||
| b8fbb89fae | |||
| f3650364b9 | |||
| 5b629ede56 | |||
| 28afeccf70 | |||
| 9467847d74 | |||
| b11a0c7778 | |||
| ff645c6fe2 | |||
| 9c3053b3f9 | |||
| 5a6c9cc777 | |||
| 6e4a1f0a21 | |||
| f8be97c12c | |||
| 4123e7aa57 | |||
| 637cc574ab | |||
| 3042f187ed | |||
| 867f742d08 | |||
| 1724212458 | |||
| 05c6ca06f8 | |||
| 8c03f0e2eb | |||
| 20c3532e01 | |||
| 6cba7f164e | |||
| c3f8fcd7b7 | |||
| caacafa090 | |||
| 0a614e4bab | |||
| c12a04c224 | |||
| 5c3b06f015 | |||
| 9520c6eeba | |||
| 70aa674226 | |||
| 422aa86874 | |||
| b44af136e7 | |||
| e54c6a04de | |||
| e1d56178c8 | |||
| 1d1d774d9f | |||
| 8dead11a25 | |||
| 53c3a130ab | |||
| 834568d7f4 | |||
| d2c6c4b369 | |||
| 636654cb71 | |||
| 55106d6d57 | |||
| a1e6a6e779 | |||
| e58cbcdb17 | |||
| 9e42dab184 | |||
| 25dc87a633 | |||
| f68663af7e | |||
| 07f8dd1cb1 | |||
| 18c15ed8d1 | |||
| 959e6a8470 | |||
| 76c2fc1776 | |||
| 6340d6652a | |||
| 87b2e29d60 | |||
| 24d390e1aa | |||
| 210f9afd66 | |||
| eb818da93f | |||
| 1c20ff3fb9 | |||
| fb87418473 | |||
| 870a20e834 | |||
| 5b7356d905 | |||
| 918c486c65 | |||
| 26e7cd2afb | |||
| 2eda63e9ae | |||
| b2902a0789 | |||
| edc3e2be84 | |||
| c6721a799d | |||
| fdfbcdf51e | |||
| aed8e68fca | |||
| 50249206df | |||
| 5480be4c25 | |||
| 436b5ff7a8 | |||
| 3536bb247e | |||
| a80a053b0a | |||
| 2642ecc737 | |||
| abfcf72a56 | |||
| 0e044804d2 | |||
| 5b9afd5329 | |||
| a983a89964 | |||
| 741a50ab97 | |||
| cf6c298b82 | |||
| 90c0fe948b | |||
| 2c84122654 | |||
| 143db5fc9d | |||
| c28ad86214 | |||
| 15f153474a | |||
| 55d66a9ea3 | |||
| 14c86daf23 | |||
| 460aaf8bb6 | |||
| 1e703a0be5 | |||
| 142e3c0177 | |||
| d4b7a2b3e9 | |||
| dac6d03666 | |||
| 3bfd58dfd9 | |||
| 2d6459b290 | |||
| 1f0f6a8d3d | |||
| 2ecb8d5413 | |||
| f1d03393de |
@@ -1,19 +0,0 @@
|
||||
version = 1
|
||||
|
||||
test_patterns = ["tests/**"]
|
||||
|
||||
exclude_patterns = [
|
||||
"tests/**",
|
||||
"docs/**",
|
||||
"setup.py",
|
||||
"setup-raw.py"
|
||||
]
|
||||
|
||||
[[analyzers]]
|
||||
name = "python"
|
||||
enabled = true
|
||||
|
||||
[analyzers.meta]
|
||||
runtime_version = "3.x.x"
|
||||
max_line_length = 99
|
||||
skip_doc_coverage = ["module", "magic", "init", "nonpublic"]
|
||||
+64
-53
@@ -13,7 +13,7 @@ Setting things up
|
||||
|
||||
.. code-block:: bash
|
||||
|
||||
$ git clone https://github.com/<your username>/python-telegram-bot --recursive
|
||||
$ git clone https://github.com/<your username>/python-telegram-bot
|
||||
$ cd python-telegram-bot
|
||||
|
||||
3. Add a track to the original repository:
|
||||
@@ -26,7 +26,7 @@ Setting things up
|
||||
|
||||
.. code-block:: bash
|
||||
|
||||
$ pip install -r requirements.txt -r requirements-dev.txt
|
||||
$ pip install -r requirements-dev-all.txt
|
||||
|
||||
|
||||
5. Install pre-commit hooks:
|
||||
@@ -67,6 +67,7 @@ Here's how to make a one-off code change.
|
||||
$ git checkout -b your-branch-name
|
||||
|
||||
3. **Make a commit to your feature branch**. Each commit should be self-contained and have a descriptive commit message that helps other developers understand why the changes were made.
|
||||
We also have a check-list for PRs `below`_.
|
||||
|
||||
- You can refer to relevant issues in the commit message by writing, e.g., "#105".
|
||||
|
||||
@@ -80,32 +81,17 @@ Here's how to make a one-off code change.
|
||||
|
||||
- The following exceptions to the above (Google's) style guides applies:
|
||||
|
||||
- Documenting types of global variables and complex types of class members can be done using the Sphinx docstring convention.
|
||||
- Documenting types of global variables and complex types of class members can be done using the Sphinx docstring convention.
|
||||
|
||||
- In addition, PTB uses the `Black`_ coder formatting. Plugins for Black exist for some `popular editors`_. You can use those instead of manually formatting everything.
|
||||
- In addition, PTB uses some formatting/styling and linting tools in the pre-commit setup. Some of those tools also have command line tools that can help to run these tools outside of the pre-commit step. If you'd like to leverage that, please have a look at the `pre-commit config file`_ for an overview of which tools (and which versions of them) are used. For example, we use `Black`_ for code formatting. Plugins for Black exist for some `popular editors`_. You can use those instead of manually formatting everything.
|
||||
|
||||
- Please ensure that the code you write is well-tested.
|
||||
- Please ensure that the code you write is well-tested and that all automated tests still pass. We
|
||||
have dedicated an `testing page`_ to help you with that.
|
||||
|
||||
- In addition to that, we provide the `dev` marker for pytest. If you write one or multiple tests and want to run only those, you can decorate them via `@pytest.mark.dev` and then run it with minimal overhead with `pytest ./path/to/test_file.py -m dev`.
|
||||
|
||||
- Don’t break backward compatibility.
|
||||
- Don't break backward compatibility.
|
||||
|
||||
- Add yourself to the AUTHORS.rst_ file in an alphabetical fashion.
|
||||
|
||||
- Before making a commit ensure that all automated tests still pass:
|
||||
|
||||
.. code-block:: bash
|
||||
|
||||
$ pytest -v
|
||||
|
||||
To run ``test_official`` (particularly useful if you made API changes), run
|
||||
|
||||
.. code-block:: bash
|
||||
|
||||
$ export TEST_OFFICIAL=true
|
||||
|
||||
prior to running the tests.
|
||||
|
||||
- If you want run style & type checks before committing run
|
||||
|
||||
.. code-block:: bash
|
||||
@@ -136,11 +122,11 @@ Here's how to make a one-off code change.
|
||||
|
||||
- When your reviewer has reviewed the code, you'll get a notification. You'll need to respond in two ways:
|
||||
|
||||
- Make a new commit addressing the comments you agree with, and push it to the same branch. Ideally, the commit message would explain what the commit does (e.g. "Fix lint error"), but if there are lots of disparate review comments, it's fine to refer to the original commit message and add something like "(address review comments)".
|
||||
- Make a new commit addressing the comments you agree with, and push it to the same branch. Ideally, the commit message would explain what the commit does (e.g. "Fix lint error"), but if there are lots of disparate review comments, it's fine to refer to the original commit message and add something like "(address review comments)".
|
||||
|
||||
- In order to keep the commit history intact, please avoid squashing or amending history and then force-pushing to the PR. Reviewers often want to look at individual commits.
|
||||
- In order to keep the commit history intact, please avoid squashing or amending history and then force-pushing to the PR. Reviewers often want to look at individual commits.
|
||||
|
||||
- In addition, please reply to each comment. Each reply should be either "Done" or a response explaining why the corresponding suggestion wasn't implemented. All comments must be resolved before LGTM can be given.
|
||||
- In addition, please reply to each comment. Each reply should be either "Done" or a response explaining why the corresponding suggestion wasn't implemented. All comments must be resolved before LGTM can be given.
|
||||
|
||||
- Resolve any merge conflicts that arise. To resolve conflicts between 'your-branch-name' (in your fork) and 'master' (in the ``python-telegram-bot`` repository), run:
|
||||
|
||||
@@ -165,6 +151,52 @@ Here's how to make a one-off code change.
|
||||
|
||||
7. **Celebrate.** Congratulations, you have contributed to ``python-telegram-bot``!
|
||||
|
||||
Check-list for PRs
|
||||
------------------
|
||||
|
||||
This checklist is a non-exhaustive reminder of things that should be done before a PR is merged, both for you as contributor and for the maintainers.
|
||||
Feel free to copy (parts of) the checklist to the PR description to remind you or the maintainers of open points or if you have questions on anything.
|
||||
|
||||
- Added ``.. versionadded:: NEXT.VERSION``, ``.. versionchanged:: NEXT.VERSION``, ``.. deprecated:: NEXT.VERSION`` or ``.. versionremoved:: NEXT.VERSION`` to the docstrings for user facing changes (for methods/class descriptions, arguments and attributes)
|
||||
- Created new or adapted existing unit tests
|
||||
- Documented code changes according to the `CSI standard <https://standards.mousepawmedia.com/en/stable/csi.html>`__
|
||||
- Added myself alphabetically to ``AUTHORS.rst`` (optional)
|
||||
- Added new classes & modules to the docs and all suitable ``__all__`` s
|
||||
- Checked the `Stability Policy <https://docs.python-telegram-bot.org/stability_policy.html>`_ in case of deprecations or changes to documented behavior
|
||||
|
||||
**If the PR contains API changes (otherwise, you can ignore this passage)**
|
||||
|
||||
- Checked the Bot API specific sections of the `Stability Policy <https://docs.python-telegram-bot.org/stability_policy.html>`_
|
||||
- Created a PR to remove functionality deprecated in the previous Bot API release (`see here <https://docs.python-telegram-bot.org/en/stable/stability_policy.html#case-2>`_)
|
||||
|
||||
- New classes:
|
||||
|
||||
- Added ``self._id_attrs`` and corresponding documentation
|
||||
- ``__init__`` accepts ``api_kwargs`` as kw-only
|
||||
|
||||
- Added new shortcuts:
|
||||
|
||||
- In :class:`~telegram.Chat` & :class:`~telegram.User` for all methods that accept ``chat/user_id``
|
||||
- In :class:`~telegram.Message` for all methods that accept ``chat_id`` and ``message_id``
|
||||
- For new :class:`~telegram.Message` shortcuts: Added ``quote`` argument if methods accepts ``reply_to_message_id``
|
||||
- In :class:`~telegram.CallbackQuery` for all methods that accept either ``chat_id`` and ``message_id`` or ``inline_message_id``
|
||||
|
||||
- If relevant:
|
||||
|
||||
- Added new constants at :mod:`telegram.constants` and shortcuts to them as class variables
|
||||
- Link new and existing constants in docstrings instead of hard-coded numbers and strings
|
||||
- Add new message types to :attr:`telegram.Message.effective_attachment`
|
||||
- Added new handlers for new update types
|
||||
|
||||
- Add the handlers to the warning loop in the :class:`~telegram.ext.ConversationHandler`
|
||||
|
||||
- Added new filters for new message (sub)types
|
||||
- Added or updated documentation for the changed class(es) and/or method(s)
|
||||
- Added the new method(s) to ``_extbot.py``
|
||||
- Added or updated ``bot_methods.rst``
|
||||
- Updated the Bot API version number in all places: ``README.rst`` (including the badge) and ``telegram.constants.BOT_API_VERSION_INFO``
|
||||
- Added logic for arbitrary callback data in :class:`telegram.ext.ExtBot` for new methods that either accept a ``reply_markup`` in some form or have a return type that is/contains :class:`~telegram.Message`
|
||||
|
||||
Documenting
|
||||
===========
|
||||
|
||||
@@ -178,13 +210,8 @@ doc strings don't have a separate documentation site they generate, instead, the
|
||||
|
||||
User facing documentation
|
||||
-------------------------
|
||||
We use `sphinx`_ to generate static HTML docs. To build them, first make sure you have the required dependencies:
|
||||
|
||||
.. code-block:: bash
|
||||
|
||||
$ pip install -r docs/requirements-docs.txt
|
||||
|
||||
then run the following from the PTB root directory:
|
||||
We use `sphinx`_ to generate static HTML docs. To build them, first make sure you're running Python 3.10 or above and have the required dependencies installed as explained above.
|
||||
Then, run the following from the PTB root directory:
|
||||
|
||||
.. code-block:: bash
|
||||
|
||||
@@ -198,7 +225,7 @@ or, if you don't have ``make`` available (e.g. on Windows):
|
||||
|
||||
Once the process terminates, you can view the built documentation by opening ``docs/build/html/index.html`` with a browser.
|
||||
|
||||
- Add ``.. versionadded:: version``, ``.. versionchanged:: version`` or ``.. deprecated:: version`` to the associated documentation of your changes, depending on what kind of change you made. This only applies if the change you made is visible to an end user. The directives should be added to class/method descriptions if their general behaviour changed and to the description of all arguments & attributes that changed.
|
||||
- Add ``.. versionadded:: NEXT.VERSION``, ``.. versionchanged:: NEXT.VERSION`` or ``.. deprecated:: NEXT.VERSION`` to the associated documentation of your changes, depending on what kind of change you made. This only applies if the change you made is visible to an end user. The directives should be added to class/method descriptions if their general behaviour changed and to the description of all arguments & attributes that changed.
|
||||
|
||||
Dev facing documentation
|
||||
------------------------
|
||||
@@ -243,27 +270,8 @@ callable we prefer that the call also uses keyword arg syntax. For example:
|
||||
This gives us the flexibility to re-order arguments and more importantly
|
||||
to add new required arguments. It's also more explicit and easier to read.
|
||||
|
||||
Properly defining optional arguments
|
||||
------------------------------------
|
||||
|
||||
It's always good to not initialize optional arguments at class creation,
|
||||
instead use ``**kwargs`` to get them. It's well known Telegram API can
|
||||
change without notice, in that case if a new argument is added it won't
|
||||
break the API classes. For example:
|
||||
|
||||
.. code-block:: python
|
||||
|
||||
# GOOD
|
||||
def __init__(self, id, name, last_name=None, **kwargs):
|
||||
self.last_name = last_name
|
||||
|
||||
|
||||
# BAD
|
||||
def __init__(self, id, name, last_name=None):
|
||||
self.last_name = last_name
|
||||
|
||||
|
||||
.. _`Code of Conduct`: https://www.python.org/psf/conduct/
|
||||
.. _`Code of Conduct`: https://policies.python.org/python.org/code-of-conduct/
|
||||
.. _`issue tracker`: https://github.com/python-telegram-bot/python-telegram-bot/issues
|
||||
.. _`Telegram group`: https://telegram.me/pythontelegrambotgroup
|
||||
.. _`PEP 8 Style Guide`: https://peps.python.org/pep-0008/
|
||||
@@ -273,9 +281,12 @@ break the API classes. For example:
|
||||
.. _AUTHORS.rst: https://github.com/python-telegram-bot/python-telegram-bot/blob/master/AUTHORS.rst
|
||||
.. _`MyPy`: https://mypy.readthedocs.io/en/stable/index.html
|
||||
.. _`here`: https://mypy.readthedocs.io/en/stable/cheat_sheet_py3.html
|
||||
.. _`pre-commit config file`: https://github.com/python-telegram-bot/python-telegram-bot/blob/master/.pre-commit-config.yaml
|
||||
.. _`Black`: https://black.readthedocs.io/en/stable/index.html
|
||||
.. _`popular editors`: https://black.readthedocs.io/en/stable/integrations/editors.html
|
||||
.. _`RTD`: https://docs.python-telegram-bot.org/
|
||||
.. _`RTD build`: https://docs.python-telegram-bot.org/en/doc-fixes
|
||||
.. _`CSI`: https://standards.mousepawmedia.com/en/stable/csi.html
|
||||
.. _`section`: #documenting
|
||||
.. _`testing page`: https://github.com/python-telegram-bot/python-telegram-bot/blob/master/tests/README.rst
|
||||
.. _`below`: #check-list-for-prs
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
name: Bug Report
|
||||
description: Create a report to help us improve
|
||||
title: "[BUG]"
|
||||
labels: ["bug :bug:"]
|
||||
labels: ["📋 triage"]
|
||||
type: '🐛 bug'
|
||||
|
||||
body:
|
||||
- type: markdown
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
name: Feature Request
|
||||
description: Suggest an idea for this project
|
||||
title: "[FEATURE]"
|
||||
labels: ["enhancement"]
|
||||
labels: ["📋 triage"]
|
||||
type: '💡 feature'
|
||||
|
||||
body:
|
||||
- type: textarea
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
name: Question
|
||||
description: Get help with errors or general questions
|
||||
title: "[QUESTION]"
|
||||
labels: ["question"]
|
||||
type: '❔ question'
|
||||
|
||||
body:
|
||||
- type: markdown
|
||||
@@ -12,6 +12,8 @@ body:
|
||||
To make it easier for us to help you, please read this [article](https://github.com/python-telegram-bot/python-telegram-bot/wiki/Ask-Right).
|
||||
|
||||
Please mind that there is also a users' [Telegram group](https://t.me/pythontelegrambotgroup) for questions about the library. Questions asked there might be answered quicker than here. Moreover, [GitHub Discussions](https://github.com/python-telegram-bot/python-telegram-bot/discussions) offer a slightly better format to discuss usage questions.
|
||||
|
||||
If you have asked the same question elsewhere (e.g. the [Telegram group](https://t.me/pythontelegrambotgroup) or [StackOverflow](https://stackoverflow.com/questions/tagged/python-telegram-bot)), provide a link to that thread.
|
||||
|
||||
- type: textarea
|
||||
id: issue-faced
|
||||
|
||||
@@ -5,6 +5,9 @@ updates:
|
||||
schedule:
|
||||
interval: "weekly"
|
||||
day: "friday"
|
||||
labels:
|
||||
- "⚙️ dependencies"
|
||||
- "🔗 python"
|
||||
|
||||
# Updates the dependencies of the GitHub Actions workflows
|
||||
- package-ecosystem: "github-actions"
|
||||
@@ -12,3 +15,6 @@ updates:
|
||||
schedule:
|
||||
interval: "monthly"
|
||||
day: "friday"
|
||||
labels:
|
||||
- "⚙️ dependencies"
|
||||
- "🔗 github-actions"
|
||||
|
||||
@@ -0,0 +1,9 @@
|
||||
# Config file for workflows/labelling.yml
|
||||
|
||||
version: 1
|
||||
|
||||
labels:
|
||||
- label: "⚙️ dependencies"
|
||||
authors: ["dependabot[bot]", "pre-commit-ci[bot]"]
|
||||
- label: "🛠 code-quality"
|
||||
authors: ["pre-commit-ci[bot]"]
|
||||
@@ -1,37 +1,6 @@
|
||||
<!--
|
||||
Hey! You're PRing? Cool! Please have a look at the below checklist. It's here to help both you and the maintainers to remember some aspects. Make sure to check out our contribution guide (https://github.com/python-telegram-bot/python-telegram-bot/blob/master/.github/CONTRIBUTING.rst).
|
||||
Hey! You're PRing? Cool!
|
||||
Please be sure to check out our contribution guide (https://github.com/python-telegram-bot/python-telegram-bot/blob/master/.github/CONTRIBUTING.rst).
|
||||
Especially, please have a look at the check list for PRs (https://github.com/python-telegram-bot/python-telegram-bot/blob/master/.github/CONTRIBUTING.rst#check-list-for-prs). Feel free to copy (parts of) the checklist to the PR description to remind you or the maintainers of open points or if you have questions on anything.
|
||||
-->
|
||||
|
||||
### Checklist for PRs
|
||||
|
||||
- [ ] Added `.. versionadded:: version`, `.. versionchanged:: version` or `.. deprecated:: version` to the docstrings for user facing changes (for methods/class descriptions, arguments and attributes)
|
||||
- [ ] Created new or adapted existing unit tests
|
||||
- [ ] Documented code changes according to the [CSI standard](https://standards.mousepawmedia.com/en/stable/csi.html)
|
||||
- [ ] Added myself alphabetically to `AUTHORS.rst` (optional)
|
||||
- [ ] Added new classes & modules to the docs and all suitable `__all__` s
|
||||
|
||||
|
||||
### If the PR contains API changes (otherwise, you can delete this passage)
|
||||
|
||||
* New classes:
|
||||
- [ ] Added `self._id_attrs` and corresponding documentation
|
||||
- [ ] `__init__` accepts `**_kwargs`
|
||||
|
||||
* Added new shortcuts:
|
||||
- [ ] In `Chat` & `User` for all methods that accept `chat/user_id`
|
||||
- [ ] In `Message` for all methods that accept `chat_id` and `message_id`
|
||||
- [ ] For new `Message` shortcuts: Added `quote` argument if methods accepts `reply_to_message_id`
|
||||
- [ ] In `CallbackQuery` for all methods that accept either `chat_id` and `message_id` or `inline_message_id`
|
||||
|
||||
* If relevant:
|
||||
|
||||
- [ ] Added new constants at `telegram.constants` and shortcuts to them as class variables
|
||||
- [ ] Link new and existing constants in docstrings instead of hard coded number and strings
|
||||
- [ ] Add new message types to `Message.effective_attachment`
|
||||
- [ ] Added new handlers for new update types
|
||||
- [ ] Add the handlers to the warning loop in the `ConversationHandler`
|
||||
- [ ] Added new filters for new message (sub)types
|
||||
- [ ] Added or updated documentation for the changed class(es) and/or method(s)
|
||||
- [ ] Added or updated `bot_methods.rst`
|
||||
- [ ] Updated the Bot API version number in all places: `README.rst` and `README_RAW.rst` (including the badge), as well as `telegram.constants.BOT_API_VERSION`
|
||||
- [ ] Added logic for arbitrary callback data in `tg.ext.Bot` for new methods that either accept a `reply_markup` in some form or have a return type that is/contains `telegram.Message`
|
||||
|
||||
@@ -1,14 +0,0 @@
|
||||
# Number of days of inactivity before an issue becomes stale
|
||||
daysUntilStale: 3
|
||||
# Number of days of inactivity before a stale issue is closed
|
||||
daysUntilClose: 2
|
||||
# Only issues or pull requests with all of these labels are check if stale. Defaults to `[]` (disabled)
|
||||
onlyLabels: question
|
||||
# Label to use when marking an issue as stale
|
||||
staleLabel: stale
|
||||
# Comment to post when marking as stale. Set to `false` to disable
|
||||
markComment: false
|
||||
# Comment to post when closing a stale issue. Set to `false` to disable
|
||||
closeComment: >
|
||||
This issue has been automatically closed due to inactivity. Feel free to comment in order to reopen
|
||||
or ask again in our Telegram support group at https://t.me/pythontelegrambotgroup.
|
||||
@@ -0,0 +1,5 @@
|
||||
<b>We've just released {tag}</b>.
|
||||
Thank you to everyone who contributed to this release.
|
||||
As usual, upgrade using <code>pip install -U python-telegram-bot</code>.
|
||||
|
||||
The release notes can be found <a href="https://docs.python-telegram-bot.org/en/{tag}/changelog.html">here</a>.
|
||||
@@ -0,0 +1,30 @@
|
||||
name: Create Chango Fragment
|
||||
on:
|
||||
pull_request:
|
||||
types:
|
||||
- opened
|
||||
- reopened
|
||||
- synchronize
|
||||
|
||||
permissions: {}
|
||||
|
||||
jobs:
|
||||
create-chango-fragment:
|
||||
permissions:
|
||||
# Give the default GITHUB_TOKEN write permission to commit and push the
|
||||
# added or changed files to the repository.
|
||||
contents: write
|
||||
name: create-chango-fragment
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
|
||||
# Create the new fragment
|
||||
- uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2
|
||||
with:
|
||||
persist-credentials: false
|
||||
- uses: Bibo-Joshi/chango@9d6bd9d7612eca5fab2c5161687011be59baaf19 # v0.4.0
|
||||
with:
|
||||
github-token: ${{ secrets.CHANGO_PAT }}
|
||||
query-issue-types: true
|
||||
|
||||
|
||||
@@ -0,0 +1,41 @@
|
||||
name: Process Dependabot PRs
|
||||
|
||||
on:
|
||||
pull_request:
|
||||
types: [opened, reopened]
|
||||
|
||||
permissions: {}
|
||||
|
||||
jobs:
|
||||
process-dependabot-prs:
|
||||
permissions:
|
||||
pull-requests: read
|
||||
contents: write
|
||||
|
||||
runs-on: ubuntu-latest
|
||||
if: ${{ github.event.pull_request.user.login == 'dependabot[bot]' }}
|
||||
steps:
|
||||
|
||||
- name: Fetch Dependabot metadata
|
||||
id: dependabot-metadata
|
||||
uses: dependabot/fetch-metadata@d7267f607e9d3fb96fc2fbe83e0af444713e90b7 # v2.3.0
|
||||
|
||||
- uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2
|
||||
with:
|
||||
ref: ${{ github.event.pull_request.head.ref }}
|
||||
persist-credentials: false
|
||||
|
||||
- name: Update Version Number in Other Files
|
||||
uses: jacobtomlinson/gha-find-replace@f1069b438f125e5395d84d1c6fd3b559a7880cb5 # v3
|
||||
with:
|
||||
find: ${{ steps.dependabot-metadata.outputs.previous-version }}
|
||||
replace: ${{ steps.dependabot-metadata.outputs.new-version }}
|
||||
regex: false
|
||||
exclude: CHANGES.rst
|
||||
|
||||
- name: Commit & Push Changes to PR
|
||||
uses: EndBug/add-and-commit@a94899bca583c204427a224a7af87c02f9b325d5 # v9.1.4
|
||||
with:
|
||||
message: 'Update version number in other files'
|
||||
committer_name: GitHub Actions
|
||||
committer_email: 41898282+github-actions[bot]@users.noreply.github.com
|
||||
@@ -0,0 +1,41 @@
|
||||
name: Test Admonitions Generation
|
||||
on:
|
||||
pull_request:
|
||||
paths:
|
||||
- telegram/**
|
||||
- docs/**
|
||||
- .github/workflows/docs-admonitions.yml
|
||||
push:
|
||||
branches:
|
||||
- master
|
||||
|
||||
permissions: {}
|
||||
|
||||
jobs:
|
||||
test-admonitions:
|
||||
name: Test Admonitions Generation
|
||||
runs-on: ${{matrix.os}}
|
||||
permissions:
|
||||
# for uploading artifacts
|
||||
actions: write
|
||||
strategy:
|
||||
matrix:
|
||||
python-version: ['3.12']
|
||||
os: [ubuntu-latest]
|
||||
fail-fast: False
|
||||
steps:
|
||||
- uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2
|
||||
with:
|
||||
persist-credentials: false
|
||||
- name: Set up Python ${{ matrix.python-version }}
|
||||
uses: actions/setup-python@42375524e23c412d93fb67b49958b491fce71c38 # v5.4.0
|
||||
with:
|
||||
python-version: ${{ matrix.python-version }}
|
||||
cache: 'pip'
|
||||
cache-dependency-path: '**/requirements*.txt'
|
||||
- name: Install dependencies
|
||||
run: |
|
||||
python -W ignore -m pip install --upgrade pip
|
||||
python -W ignore -m pip install -r requirements-dev-all.txt
|
||||
- name: Test autogeneration of admonitions
|
||||
run: pytest -v --tb=short tests/docs/admonition_inserter.py
|
||||
@@ -3,6 +3,11 @@ on:
|
||||
schedule:
|
||||
# First day of month at 05:46 in every 2nd month
|
||||
- cron: '46 5 1 */2 *'
|
||||
pull_request:
|
||||
paths:
|
||||
- .github/workflows/docs-linkcheck.yml
|
||||
|
||||
permissions: {}
|
||||
|
||||
jobs:
|
||||
test-sphinx-build:
|
||||
@@ -10,20 +15,27 @@ jobs:
|
||||
runs-on: ${{matrix.os}}
|
||||
strategy:
|
||||
matrix:
|
||||
python-version: [3.7]
|
||||
python-version: ['3.12']
|
||||
os: [ubuntu-latest]
|
||||
fail-fast: False
|
||||
steps:
|
||||
- uses: actions/checkout@v3
|
||||
- uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2
|
||||
with:
|
||||
persist-credentials: false
|
||||
- name: Set up Python ${{ matrix.python-version }}
|
||||
uses: actions/setup-python@v3
|
||||
uses: actions/setup-python@42375524e23c412d93fb67b49958b491fce71c38 # v5.4.0
|
||||
with:
|
||||
python-version: ${{ matrix.python-version }}
|
||||
- name: Install dependencies
|
||||
run: |
|
||||
python -W ignore -m pip install --upgrade pip
|
||||
python -W ignore -m pip install -r requirements.txt
|
||||
python -W ignore -m pip install -r requirements-dev.txt
|
||||
python -W ignore -m pip install -r docs/requirements-docs.txt
|
||||
python -W ignore -m pip install -r requirements-dev-all.txt
|
||||
- name: Check Links
|
||||
run: sphinx-build docs/source docs/build/html -W --keep-going -j auto -b linkcheck
|
||||
- name: Upload linkcheck output
|
||||
# Run also if the previous steps failed
|
||||
if: always()
|
||||
uses: actions/upload-artifact@6f51ac03b9356f520e9adb1b1b7802705f340c2b # v4.5.0
|
||||
with:
|
||||
name: linkcheck-output
|
||||
path: docs/build/html/output.*
|
||||
|
||||
@@ -1,34 +0,0 @@
|
||||
name: Test Documentation Build
|
||||
on:
|
||||
pull_request:
|
||||
branches:
|
||||
- master
|
||||
- doc-fixes
|
||||
push:
|
||||
branches:
|
||||
- master
|
||||
- doc-fixes
|
||||
|
||||
jobs:
|
||||
test-sphinx-build:
|
||||
name: test-sphinx-build
|
||||
runs-on: ${{matrix.os}}
|
||||
strategy:
|
||||
matrix:
|
||||
python-version: [3.7]
|
||||
os: [ubuntu-latest]
|
||||
fail-fast: False
|
||||
steps:
|
||||
- uses: actions/checkout@v3
|
||||
- name: Set up Python ${{ matrix.python-version }}
|
||||
uses: actions/setup-python@v3
|
||||
with:
|
||||
python-version: ${{ matrix.python-version }}
|
||||
- name: Install dependencies
|
||||
run: |
|
||||
python -W ignore -m pip install --upgrade pip
|
||||
python -W ignore -m pip install -r requirements.txt
|
||||
python -W ignore -m pip install -r requirements-dev.txt
|
||||
python -W ignore -m pip install -r docs/requirements-docs.txt
|
||||
- name: Build docs
|
||||
run: sphinx-build docs/source docs/build/html -W --keep-going -j auto
|
||||
@@ -0,0 +1,33 @@
|
||||
name: GitHub Actions Security Analysis
|
||||
|
||||
on:
|
||||
push:
|
||||
branches:
|
||||
- master
|
||||
pull_request:
|
||||
|
||||
permissions: {}
|
||||
|
||||
jobs:
|
||||
zizmor:
|
||||
name: Security Analysis with zizmor
|
||||
runs-on: ubuntu-latest
|
||||
permissions:
|
||||
contents: read
|
||||
security-events: write
|
||||
steps:
|
||||
- name: Checkout repository
|
||||
uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2
|
||||
with:
|
||||
persist-credentials: false
|
||||
- name: Install the latest version of uv
|
||||
uses: astral-sh/setup-uv@f94ec6bedd8674c4426838e6b50417d36b6ab231 # v5.3.1
|
||||
- name: Run zizmor
|
||||
run: uvx zizmor --persona=pedantic --format sarif . > results.sarif
|
||||
env:
|
||||
GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
||||
- name: Upload SARIF file
|
||||
uses: github/codeql-action/upload-sarif@b56ba49b26e50535fa1e7f7db0f4f7b4bf65d80d # v3.28.10
|
||||
with:
|
||||
sarif_file: results.sarif
|
||||
category: zizmor
|
||||
@@ -0,0 +1,19 @@
|
||||
name: PR Labeler
|
||||
|
||||
on:
|
||||
pull_request:
|
||||
types: [opened]
|
||||
|
||||
permissions: {}
|
||||
|
||||
jobs:
|
||||
pre-commit-ci:
|
||||
permissions:
|
||||
contents: read # for srvaroa/labeler to read config file
|
||||
pull-requests: write # for srvaroa/labeler to add labels in PR
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: srvaroa/labeler@0a20eccb8c94a1ee0bed5f16859aece1c45c3e55 # v1.13.0
|
||||
# Config file at .github/labeler.yml
|
||||
env:
|
||||
GITHUB_TOKEN: "${{ secrets.GITHUB_TOKEN }}"
|
||||
@@ -3,16 +3,23 @@ name: 'Lock Closed Threads'
|
||||
on:
|
||||
schedule:
|
||||
- cron: '8 4 * * *'
|
||||
- cron: '42 17 * * *'
|
||||
|
||||
permissions: {}
|
||||
|
||||
jobs:
|
||||
lock:
|
||||
runs-on: ubuntu-latest
|
||||
permissions:
|
||||
# For locking the threads
|
||||
issues: write
|
||||
pull-requests: write
|
||||
steps:
|
||||
- uses: dessant/lock-threads@v3.0.0
|
||||
- uses: dessant/lock-threads@1bf7ec25051fe7c00bdd17e6a7cf3d7bfb7dc771 # v5.0.1
|
||||
with:
|
||||
github-token: ${{ github.token }}
|
||||
issue-inactive-days: '7'
|
||||
issue-lock-reason: ''
|
||||
pr-inactive-days: '7'
|
||||
pr-lock-reason: ''
|
||||
# Don't lock Discussions
|
||||
process-only: 'issues, prs'
|
||||
|
||||
@@ -1,19 +0,0 @@
|
||||
name: Warning maintainers
|
||||
on:
|
||||
pull_request_target:
|
||||
paths:
|
||||
- requirements.txt
|
||||
- requirements-dev.txt
|
||||
- .pre-commit-config.yaml
|
||||
permissions:
|
||||
pull-requests: write
|
||||
jobs:
|
||||
job:
|
||||
runs-on: ubuntu-latest
|
||||
name: about pre-commit and dependency change
|
||||
steps:
|
||||
- name: running the check
|
||||
uses: Poolitzer/notifier-action@master
|
||||
with:
|
||||
notify-message: Hey! Looks like you edited the (dev) requirements or the pre-commit hooks. I'm just a friendly reminder to keep the pre-commit hook versions in sync with the dev requirements and the additional dependencies for the hooks in sync with the requirements :)
|
||||
repo-token: ${{ secrets.GITHUB_TOKEN }}
|
||||
@@ -1,18 +0,0 @@
|
||||
name: Warning maintainers
|
||||
on:
|
||||
pull_request_target:
|
||||
paths:
|
||||
- README.rst
|
||||
- README_RAW.rst
|
||||
permissions:
|
||||
pull-requests: write
|
||||
jobs:
|
||||
job:
|
||||
runs-on: ubuntu-latest
|
||||
name: about readme change
|
||||
steps:
|
||||
- name: running the check
|
||||
uses: Poolitzer/notifier-action@master
|
||||
with:
|
||||
notify-message: Hey! Looks like you edited README.rst or README_RAW.rst. I'm just a friendly reminder to apply relevant changes to both of those files :)
|
||||
repo-token: ${{ secrets.GITHUB_TOKEN }}
|
||||
@@ -0,0 +1,164 @@
|
||||
name: Publish to PyPI
|
||||
|
||||
on:
|
||||
# manually trigger the workflow
|
||||
workflow_dispatch:
|
||||
|
||||
permissions: {}
|
||||
|
||||
jobs:
|
||||
build:
|
||||
name: Build Distribution
|
||||
runs-on: ubuntu-latest
|
||||
outputs:
|
||||
TAG: ${{ steps.get_tag.outputs.TAG }}
|
||||
permissions:
|
||||
# for uploading artifacts
|
||||
actions: write
|
||||
|
||||
steps:
|
||||
- uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2
|
||||
with:
|
||||
persist-credentials: false
|
||||
- name: Set up Python
|
||||
uses: actions/setup-python@42375524e23c412d93fb67b49958b491fce71c38 # v5.4.0
|
||||
with:
|
||||
python-version: "3.x"
|
||||
- name: Install pypa/build
|
||||
run: >-
|
||||
python3 -m pip install build --user
|
||||
- name: Build a binary wheel and a source tarball
|
||||
run: python3 -m build
|
||||
- name: Store the distribution packages
|
||||
uses: actions/upload-artifact@6f51ac03b9356f520e9adb1b1b7802705f340c2b # v4.5.0
|
||||
with:
|
||||
name: python-package-distributions
|
||||
path: dist/
|
||||
- name: Get Tag Name
|
||||
id: get_tag
|
||||
run: |
|
||||
pip install .
|
||||
TAG=$(python -c "from telegram import __version__; print(f'v{__version__}')")
|
||||
echo "TAG=$TAG" >> $GITHUB_OUTPUT
|
||||
|
||||
publish-to-pypi:
|
||||
name: Publish to PyPI
|
||||
needs:
|
||||
- build
|
||||
runs-on: ubuntu-latest
|
||||
environment:
|
||||
name: release_pypi
|
||||
url: https://pypi.org/p/python-telegram-bot
|
||||
permissions:
|
||||
id-token: write # IMPORTANT: mandatory for trusted publishing
|
||||
actions: read # for downloading artifacts
|
||||
|
||||
steps:
|
||||
- name: Download all the dists
|
||||
uses: actions/download-artifact@fa0a91b85d4f404e444e00e005971372dc801d16 # v4.1.8
|
||||
with:
|
||||
name: python-package-distributions
|
||||
path: dist/
|
||||
- name: Publish to PyPI
|
||||
uses: pypa/gh-action-pypi-publish@76f52bc884231f62b9a034ebfe128415bbaabdfc # v1.12.4
|
||||
|
||||
compute-signatures:
|
||||
name: Compute SHA1 Sums and Sign with Sigstore
|
||||
runs-on: ubuntu-latest
|
||||
needs:
|
||||
- publish-to-pypi
|
||||
|
||||
permissions:
|
||||
id-token: write # IMPORTANT: mandatory for sigstore
|
||||
actions: write # for up/downloading artifacts
|
||||
|
||||
steps:
|
||||
- name: Download all the dists
|
||||
uses: actions/download-artifact@fa0a91b85d4f404e444e00e005971372dc801d16 # v4.1.8
|
||||
with:
|
||||
name: python-package-distributions
|
||||
path: dist/
|
||||
- name: Compute SHA1 Sums
|
||||
run: |
|
||||
# Compute SHA1 sum of the distribution packages and save it to a file with the same name,
|
||||
# but with .sha1 extension
|
||||
for file in dist/*; do
|
||||
sha1sum $file > $file.sha1
|
||||
done
|
||||
- name: Sign the dists with Sigstore
|
||||
uses: sigstore/gh-action-sigstore-python@f514d46b907ebcd5bedc05145c03b69c1edd8b46 # v3.0.0
|
||||
with:
|
||||
inputs: >-
|
||||
./dist/*.tar.gz
|
||||
./dist/*.whl
|
||||
- name: Store the distribution packages and signatures
|
||||
uses: actions/upload-artifact@6f51ac03b9356f520e9adb1b1b7802705f340c2b # v4.5.0
|
||||
with:
|
||||
name: python-package-distributions-and-signatures
|
||||
path: dist/
|
||||
|
||||
github-release:
|
||||
name: Upload to GitHub Release
|
||||
needs:
|
||||
- build
|
||||
- compute-signatures
|
||||
|
||||
runs-on: ubuntu-latest
|
||||
|
||||
permissions:
|
||||
contents: write # IMPORTANT: mandatory for making GitHub Releases
|
||||
actions: read # for downloading artifacts
|
||||
|
||||
steps:
|
||||
- name: Download all the dists
|
||||
uses: actions/download-artifact@fa0a91b85d4f404e444e00e005971372dc801d16 # v4.1.8
|
||||
with:
|
||||
name: python-package-distributions-and-signatures
|
||||
path: dist/
|
||||
- name: Create GitHub Release
|
||||
env:
|
||||
GITHUB_TOKEN: ${{ github.token }}
|
||||
TAG: ${{ needs.build.outputs.TAG }}
|
||||
# Create a tag and a GitHub Release. The description is filled by the static template, we
|
||||
# just insert the correct tag in the template.
|
||||
run: >-
|
||||
sed "s/{tag}/$TAG/g" .github/workflows/assets/release_template.html |
|
||||
gh release create
|
||||
"$TAG"
|
||||
--repo '${{ github.repository }}'
|
||||
--notes-file -
|
||||
- name: Upload artifact signatures to GitHub Release
|
||||
env:
|
||||
GITHUB_TOKEN: ${{ github.token }}
|
||||
TAG: ${{ needs.build.outputs.TAG }}
|
||||
# Upload to GitHub Release using the `gh` CLI.
|
||||
# `dist/` contains the built packages, and the
|
||||
# sigstore-produced signatures and certificates.
|
||||
run: >-
|
||||
gh release upload
|
||||
"$TAG" dist/**
|
||||
--repo '${{ github.repository }}'
|
||||
|
||||
telegram-channel:
|
||||
name: Publish to Telegram Channel
|
||||
needs:
|
||||
- github-release
|
||||
|
||||
runs-on: ubuntu-latest
|
||||
environment:
|
||||
name: release_pypi
|
||||
permissions: {}
|
||||
|
||||
steps:
|
||||
- name: Publish to Telegram Channel
|
||||
env:
|
||||
TAG: ${{ needs.build.outputs.TAG }}
|
||||
# This secret is configured only for the `pypi-release` branch
|
||||
BOT_TOKEN: ${{ secrets.CHANNEL_BOT_TOKEN }}
|
||||
run: >-
|
||||
sed "s/{tag}/$TAG/g" .github/workflows/assets/release_template.html |
|
||||
curl
|
||||
-X POST "https://api.telegram.org/bot$BOT_TOKEN/sendMessage"
|
||||
-d "chat_id=@pythontelegrambotchannel"
|
||||
-d "parse_mode=HTML"
|
||||
--data-urlencode "text@-"
|
||||
@@ -0,0 +1,143 @@
|
||||
name: Publish to Test PyPI
|
||||
|
||||
on:
|
||||
# manually trigger the workflow
|
||||
workflow_dispatch:
|
||||
|
||||
permissions: {}
|
||||
|
||||
jobs:
|
||||
build:
|
||||
name: Build Distribution
|
||||
runs-on: ubuntu-latest
|
||||
outputs:
|
||||
TAG: ${{ steps.get_tag.outputs.TAG }}
|
||||
permissions:
|
||||
# for uploading artifacts
|
||||
actions: write
|
||||
|
||||
steps:
|
||||
- uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2
|
||||
with:
|
||||
persist-credentials: false
|
||||
- name: Set up Python
|
||||
uses: actions/setup-python@42375524e23c412d93fb67b49958b491fce71c38 # v5.4.0
|
||||
with:
|
||||
python-version: "3.x"
|
||||
- name: Install pypa/build
|
||||
run: >-
|
||||
python3 -m pip install build --user
|
||||
- name: Build a binary wheel and a source tarball
|
||||
run: python3 -m build
|
||||
- name: Store the distribution packages
|
||||
uses: actions/upload-artifact@6f51ac03b9356f520e9adb1b1b7802705f340c2b # v4.5.0
|
||||
with:
|
||||
name: python-package-distributions
|
||||
path: dist/
|
||||
- name: Get Tag Name
|
||||
id: get_tag
|
||||
run: |
|
||||
pip install .
|
||||
TAG=$(python -c "from telegram import __version__; print(f'v{__version__}')")
|
||||
echo "TAG=$TAG" >> $GITHUB_OUTPUT
|
||||
|
||||
publish-to-test-pypi:
|
||||
name: Publish to Test PyPI
|
||||
needs:
|
||||
- build
|
||||
runs-on: ubuntu-latest
|
||||
environment:
|
||||
name: release_test_pypi
|
||||
url: https://test.pypi.org/p/python-telegram-bot
|
||||
permissions:
|
||||
id-token: write # IMPORTANT: mandatory for trusted publishing
|
||||
actions: read # for downloading artifacts
|
||||
|
||||
steps:
|
||||
- name: Download all the dists
|
||||
uses: actions/download-artifact@fa0a91b85d4f404e444e00e005971372dc801d16 # v4.1.8
|
||||
with:
|
||||
name: python-package-distributions
|
||||
path: dist/
|
||||
- name: Publish to Test PyPI
|
||||
uses: pypa/gh-action-pypi-publish@76f52bc884231f62b9a034ebfe128415bbaabdfc # v1.12.4
|
||||
with:
|
||||
repository-url: https://test.pypi.org/legacy/
|
||||
|
||||
compute-signatures:
|
||||
name: Compute SHA1 Sums and Sign with Sigstore
|
||||
runs-on: ubuntu-latest
|
||||
needs:
|
||||
- publish-to-test-pypi
|
||||
|
||||
permissions:
|
||||
id-token: write # IMPORTANT: mandatory for sigstore
|
||||
actions: write # for up/downloading artifacts
|
||||
|
||||
steps:
|
||||
- name: Download all the dists
|
||||
uses: actions/download-artifact@fa0a91b85d4f404e444e00e005971372dc801d16 # v4.1.8
|
||||
with:
|
||||
name: python-package-distributions
|
||||
path: dist/
|
||||
- name: Compute SHA1 Sums
|
||||
run: |
|
||||
# Compute SHA1 sum of the distribution packages and save it to a file with the same name,
|
||||
# but with .sha1 extension
|
||||
for file in dist/*; do
|
||||
sha1sum $file > $file.sha1
|
||||
done
|
||||
- name: Sign the dists with Sigstore
|
||||
uses: sigstore/gh-action-sigstore-python@f514d46b907ebcd5bedc05145c03b69c1edd8b46 # v3.0.0
|
||||
with:
|
||||
inputs: >-
|
||||
./dist/*.tar.gz
|
||||
./dist/*.whl
|
||||
- name: Store the distribution packages and signatures
|
||||
uses: actions/upload-artifact@6f51ac03b9356f520e9adb1b1b7802705f340c2b # v4.5.0
|
||||
with:
|
||||
name: python-package-distributions-and-signatures
|
||||
path: dist/
|
||||
|
||||
github-test-release:
|
||||
name: Upload to GitHub Release Draft
|
||||
needs:
|
||||
- build
|
||||
- compute-signatures
|
||||
|
||||
runs-on: ubuntu-latest
|
||||
|
||||
permissions:
|
||||
contents: write # IMPORTANT: mandatory for making GitHub Releases
|
||||
actions: read # for downloading artifacts
|
||||
|
||||
steps:
|
||||
- name: Download all the dists
|
||||
uses: actions/download-artifact@fa0a91b85d4f404e444e00e005971372dc801d16 # v4.1.8
|
||||
with:
|
||||
name: python-package-distributions-and-signatures
|
||||
path: dist/
|
||||
- name: Create GitHub Release
|
||||
env:
|
||||
GITHUB_TOKEN: ${{ github.token }}
|
||||
TAG: ${{ needs.build.outputs.TAG }}
|
||||
# Create a tag and a GitHub Release *draft*. The description is filled by the static
|
||||
# template, we just insert the correct tag in the template.
|
||||
run: >-
|
||||
sed "s/{tag}/$TAG/g" .github/workflows/assets/release_template.html |
|
||||
gh release create
|
||||
"$TAG"
|
||||
--repo '${{ github.repository }}'
|
||||
--draft
|
||||
--notes-file -
|
||||
- name: Upload artifact signatures to GitHub Release
|
||||
env:
|
||||
GITHUB_TOKEN: ${{ github.token }}
|
||||
TAG: ${{ needs.build.outputs.TAG }}
|
||||
# Upload to GitHub Release using the `gh` CLI.
|
||||
# `dist/` contains the built packages, and the
|
||||
# sigstore-produced signatures and certificates.
|
||||
run: >-
|
||||
gh release upload
|
||||
"$TAG" dist/**
|
||||
--repo '${{ github.repository }}'
|
||||
@@ -0,0 +1,24 @@
|
||||
name: 'Mark & close stale questions'
|
||||
on:
|
||||
schedule:
|
||||
- cron: '42 2 * * *'
|
||||
|
||||
permissions: {}
|
||||
|
||||
jobs:
|
||||
stale:
|
||||
runs-on: ubuntu-latest
|
||||
permissions:
|
||||
# For adding labels and closing
|
||||
issues: write
|
||||
steps:
|
||||
- uses: actions/stale@5bef64f19d7facfb25b37b414482c7164d639639 # v9.1.0
|
||||
with:
|
||||
# PRs never get stale
|
||||
days-before-stale: 3
|
||||
days-before-close: 2
|
||||
days-before-pr-stale: -1
|
||||
stale-issue-label: '📋 stale'
|
||||
only-labels: 'question'
|
||||
stale-issue-message: ''
|
||||
close-issue-message: 'This issue has been automatically closed due to inactivity. Feel free to comment in order to reopen or ask again in our Telegram support group at https://t.me/pythontelegrambotgroup.'
|
||||
@@ -1,93 +0,0 @@
|
||||
name: GitHub Actions
|
||||
on:
|
||||
pull_request:
|
||||
branches:
|
||||
- master
|
||||
push:
|
||||
branches:
|
||||
- master
|
||||
schedule:
|
||||
# Run monday and friday morning at 03:07 - odd time to spread load on GitHub Actions
|
||||
- cron: '7 3 * * 1,5'
|
||||
|
||||
jobs:
|
||||
pytest:
|
||||
name: pytest
|
||||
runs-on: ${{matrix.os}}
|
||||
strategy:
|
||||
matrix:
|
||||
python-version: ['3.7', '3.8', '3.9', '3.10']
|
||||
os: [ubuntu-latest, windows-latest, macos-latest]
|
||||
fail-fast: False
|
||||
steps:
|
||||
- uses: actions/checkout@v3
|
||||
- name: Set up Python ${{ matrix.python-version }}
|
||||
uses: actions/setup-python@v3
|
||||
with:
|
||||
python-version: ${{ matrix.python-version }}
|
||||
- name: Install dependencies
|
||||
run: |
|
||||
python -W ignore -m pip install --upgrade pip
|
||||
python -W ignore -m pip install -U codecov pytest-cov
|
||||
python -W ignore -m pip install -r requirements.txt
|
||||
python -W ignore -m pip install -r requirements-dev.txt
|
||||
|
||||
- name: Test with pytest
|
||||
# We run 3 different suites here
|
||||
# 1. Test just utils.datetime.py without pytz being installed
|
||||
# 2. Test just test_no_passport.py without passport dependencies being installed
|
||||
# 3. Test everything else
|
||||
# The first & second one are achieved by mocking the corresponding import
|
||||
# See test_helpers.py & test_no_passport.py for details
|
||||
run: |
|
||||
pytest -v --cov -k test_no_passport.py
|
||||
no_passport_exit=$?
|
||||
export TEST_NO_PASSPORT='false'
|
||||
pytest -v --cov --cov-append -k test_helpers.py
|
||||
no_pytz_exit=$?
|
||||
export TEST_NO_PYTZ='false'
|
||||
pytest -v --cov --cov-append
|
||||
full_exit=$?
|
||||
special_exit=$(( no_pytz_exit > no_passport_exit ? no_pytz_exit : no_passport_exit ))
|
||||
global_exit=$(( special_exit > full_exit ? special_exit : full_exit ))
|
||||
exit ${global_exit}
|
||||
env:
|
||||
JOB_INDEX: ${{ strategy.job-index }}
|
||||
BOTS: W3sidG9rZW4iOiAiNjk2MTg4NzMyOkFBR1Z3RUtmSEhsTmpzY3hFRE5LQXdraEdzdFpfa28xbUMwIiwgInBheW1lbnRfcHJvdmlkZXJfdG9rZW4iOiAiMjg0Njg1MDYzOlRFU1Q6WldGaU1UUmxNbVF5TnpNeSIsICJib3RfbmFtZSI6ICJQVEIgdGVzdHMgb24gVHJhdmlzIHVzaW5nIENQeXRob24gMi43IiwgInN1cGVyX2dyb3VwX2lkIjogIi0xMDAxMzkwOTgzOTk3IiwgImJvdF91c2VybmFtZSI6ICJAcHRiX3RyYXZpc19jcHl0aG9uXzI3X2JvdCJ9LCB7InRva2VuIjogIjY3MTQ2ODg4NjpBQUdQR2ZjaVJJQlVORmU4MjR1SVZkcTdKZTNfWW5BVE5HdyIsICJwYXltZW50X3Byb3ZpZGVyX3Rva2VuIjogIjI4NDY4NTA2MzpURVNUOlpHWXdPVGxrTXpNeE4yWTIiLCAiYm90X25hbWUiOiAiUFRCIHRlc3RzIG9uIFRyYXZpcyB1c2luZyBDUHl0aG9uIDMuNCIsICJzdXBlcl9ncm91cF9pZCI6ICItMTAwMTQ0NjAyMjUyMiIsICJib3RfdXNlcm5hbWUiOiAiQHB0Yl90cmF2aXNfY3B5dGhvbl8zNF9ib3QifSwgeyJ0b2tlbiI6ICI2MjkzMjY1Mzg6QUFGUnJaSnJCN29CM211ekdzR0pYVXZHRTVDUXpNNUNVNG8iLCAicGF5bWVudF9wcm92aWRlcl90b2tlbiI6ICIyODQ2ODUwNjM6VEVTVDpNbU01WVdKaFl6a3hNMlUxIiwgImJvdF9uYW1lIjogIlBUQiB0ZXN0cyBvbiBUcmF2aXMgdXNpbmcgQ1B5dGhvbiAzLjUiLCAic3VwZXJfZ3JvdXBfaWQiOiAiLTEwMDE0OTY5MTc3NTAiLCAiYm90X3VzZXJuYW1lIjogIkBwdGJfdHJhdmlzX2NweXRob25fMzVfYm90In0sIHsidG9rZW4iOiAiNjQwMjA4OTQzOkFBRmhCalFwOXFtM1JUeFN6VXBZekJRakNsZS1Kano1aGNrIiwgInBheW1lbnRfcHJvdmlkZXJfdG9rZW4iOiAiMjg0Njg1MDYzOlRFU1Q6WXpoa1pUZzFOamMxWXpWbCIsICJib3RfbmFtZSI6ICJQVEIgdGVzdHMgb24gVHJhdmlzIHVzaW5nIENQeXRob24gMy42IiwgInN1cGVyX2dyb3VwX2lkIjogIi0xMDAxMzMzODcxNDYxIiwgImJvdF91c2VybmFtZSI6ICJAcHRiX3RyYXZpc19jcHl0aG9uXzM2X2JvdCJ9LCB7InRva2VuIjogIjY5NTEwNDA4ODpBQUhmenlsSU9qU0lJUy1lT25JMjB5MkUyMEhvZEhzZnotMCIsICJwYXltZW50X3Byb3ZpZGVyX3Rva2VuIjogIjI4NDY4NTA2MzpURVNUOk9HUTFNRGd3WmpJd1pqRmwiLCAiYm90X25hbWUiOiAiUFRCIHRlc3RzIG9uIFRyYXZpcyB1c2luZyBDUHl0aG9uIDMuNyIsICJzdXBlcl9ncm91cF9pZCI6ICItMTAwMTQ3ODI5MzcxNCIsICJib3RfdXNlcm5hbWUiOiAiQHB0Yl90cmF2aXNfY3B5dGhvbl8zN19ib3QifSwgeyJ0b2tlbiI6ICI2OTE0MjM1NTQ6QUFGOFdrakNaYm5IcVBfaTZHaFRZaXJGRWxackdhWU9oWDAiLCAicGF5bWVudF9wcm92aWRlcl90b2tlbiI6ICIyODQ2ODUwNjM6VEVTVDpZamM1TlRoaU1tUXlNV1ZoIiwgImJvdF9uYW1lIjogIlBUQiB0ZXN0cyBvbiBUcmF2aXMgdXNpbmcgUHlQeSAyLjciLCAic3VwZXJfZ3JvdXBfaWQiOiAiLTEwMDEzNjM5MzI1NzMiLCAiYm90X3VzZXJuYW1lIjogIkBwdGJfdHJhdmlzX3B5cHlfMjdfYm90In0sIHsidG9rZW4iOiAiNjg0MzM5OTg0OkFBRk1nRUVqcDAxcjVyQjAwN3lDZFZOc2c4QWxOc2FVLWNjIiwgInBheW1lbnRfcHJvdmlkZXJfdG9rZW4iOiAiMjg0Njg1MDYzOlRFU1Q6TVRBek1UWTNNR1V5TmpnMCIsICJib3RfbmFtZSI6ICJQVEIgdGVzdHMgb24gVHJhdmlzIHVzaW5nIFB5UHkgMy41IiwgInN1cGVyX2dyb3VwX2lkIjogIi0xMDAxNDA3ODM2NjA1IiwgImJvdF91c2VybmFtZSI6ICJAcHRiX3RyYXZpc19weXB5XzM1X2JvdCJ9LCB7InRva2VuIjogIjY5MDA5MTM0NzpBQUZMbVI1cEFCNVljcGVfbU9oN3pNNEpGQk9oMHozVDBUbyIsICJwYXltZW50X3Byb3ZpZGVyX3Rva2VuIjogIjI4NDY4NTA2MzpURVNUOlpEaGxOekU1TURrd1lXSmkiLCAiYm90X25hbWUiOiAiUFRCIHRlc3RzIG9uIEFwcFZleW9yIHVzaW5nIENQeXRob24gMy40IiwgInN1cGVyX2dyb3VwX2lkIjogIi0xMDAxMjc5NjAwMDI2IiwgImJvdF91c2VybmFtZSI6ICJAcHRiX2FwcHZleW9yX2NweXRob25fMzRfYm90In0sIHsidG9rZW4iOiAiNjk0MzA4MDUyOkFBRUIyX3NvbkNrNTVMWTlCRzlBTy1IOGp4aVBTNTVvb0JBIiwgInBheW1lbnRfcHJvdmlkZXJfdG9rZW4iOiAiMjg0Njg1MDYzOlRFU1Q6WW1aaVlXWm1NakpoWkdNeSIsICJib3RfbmFtZSI6ICJQVEIgdGVzdHMgb24gQXBwVmV5b3IgdXNpbmcgQ1B5dGhvbiAyLjciLCAic3VwZXJfZ3JvdXBfaWQiOiAiLTEwMDEyOTMwNzkxNjUiLCAiYm90X3VzZXJuYW1lIjogIkBwdGJfYXBwdmV5b3JfY3B5dGhvbl8yN19ib3QifSwgeyJ0b2tlbiI6ICIxMDU1Mzk3NDcxOkFBRzE4bkJfUzJXQXd1SjNnN29oS0JWZ1hYY2VNbklPeVNjIiwgInBheW1lbnRfcHJvdmlkZXJfdG9rZW4iOiAiMjg0Njg1MDYzOlRFU1Q6TmpBd056QXpZalZpTkdOayIsICJuYW1lIjogIlBUQiB0ZXN0cyBbMF0iLCAic3VwZXJfZ3JvdXBfaWQiOiAiLTEwMDExODU1MDk2MzYiLCAidXNlcm5hbWUiOiAicHRiXzBfYm90In0sIHsidG9rZW4iOiAiMTA0NzMyNjc3MTpBQUY4bk90ODFGcFg4bGJidno4VWV3UVF2UmZUYkZmQnZ1SSIsICJwYXltZW50X3Byb3ZpZGVyX3Rva2VuIjogIjI4NDY4NTA2MzpURVNUOllUVTFOVEk0WkdSallqbGkiLCAibmFtZSI6ICJQVEIgdGVzdHMgWzFdIiwgInN1cGVyX2dyb3VwX2lkIjogIi0xMDAxNDg0Nzk3NjEyIiwgInVzZXJuYW1lIjogInB0Yl8xX2JvdCJ9LCB7InRva2VuIjogIjk3MTk5Mjc0NTpBQUdPa09hVzBOSGpnSXY1LTlqUWJPajR2R3FkaFNGLVV1cyIsICJwYXltZW50X3Byb3ZpZGVyX3Rva2VuIjogIjI4NDY4NTA2MzpURVNUOk5XWmtNV1ZoWWpsallqVTUiLCAibmFtZSI6ICJQVEIgdGVzdHMgWzJdIiwgInN1cGVyX2dyb3VwX2lkIjogIi0xMDAxNDAyMjU1MDcwIiwgInVzZXJuYW1lIjogInB0Yl8yX2JvdCJ9XQ==
|
||||
TEST_NO_PYTZ : "true"
|
||||
TEST_NO_PASSPORT: "true"
|
||||
TEST_BUILD: "true"
|
||||
shell: bash --noprofile --norc {0}
|
||||
|
||||
- name: Submit coverage
|
||||
uses: codecov/codecov-action@v3
|
||||
with:
|
||||
env_vars: OS,PYTHON
|
||||
name: ${{ matrix.os }}-${{ matrix.python-version }}
|
||||
fail_ci_if_error: true
|
||||
test_official:
|
||||
name: test-official
|
||||
runs-on: ${{matrix.os}}
|
||||
strategy:
|
||||
matrix:
|
||||
python-version: [3.7]
|
||||
os: [ubuntu-latest]
|
||||
fail-fast: False
|
||||
steps:
|
||||
- uses: actions/checkout@v3
|
||||
- name: Set up Python ${{ matrix.python-version }}
|
||||
uses: actions/setup-python@v3
|
||||
with:
|
||||
python-version: ${{ matrix.python-version }}
|
||||
- name: Install dependencies
|
||||
run: |
|
||||
python -W ignore -m pip install --upgrade pip
|
||||
python -W ignore -m pip install -r requirements.txt
|
||||
python -W ignore -m pip install -r requirements-dev.txt
|
||||
- name: Compare to official api
|
||||
run: |
|
||||
pytest -v tests/test_official.py
|
||||
exit $?
|
||||
env:
|
||||
TEST_OFFICIAL: "true"
|
||||
shell: bash --noprofile --norc {0}
|
||||
@@ -0,0 +1,51 @@
|
||||
name: Bot API Tests
|
||||
on:
|
||||
pull_request:
|
||||
paths:
|
||||
- telegram/**
|
||||
- tests/**
|
||||
push:
|
||||
branches:
|
||||
- master
|
||||
schedule:
|
||||
# Run monday and friday morning at 03:07 - odd time to spread load on GitHub Actions
|
||||
- cron: '7 3 * * 1,5'
|
||||
|
||||
permissions: {}
|
||||
|
||||
jobs:
|
||||
check-conformity:
|
||||
name: check-conformity
|
||||
runs-on: ${{matrix.os}}
|
||||
strategy:
|
||||
matrix:
|
||||
python-version: [3.11]
|
||||
os: [ubuntu-latest]
|
||||
fail-fast: False
|
||||
steps:
|
||||
- uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2
|
||||
with:
|
||||
persist-credentials: false
|
||||
- name: Set up Python ${{ matrix.python-version }}
|
||||
uses: actions/setup-python@42375524e23c412d93fb67b49958b491fce71c38 # v5.4.0
|
||||
with:
|
||||
python-version: ${{ matrix.python-version }}
|
||||
- name: Install dependencies
|
||||
run: |
|
||||
python -W ignore -m pip install --upgrade pip
|
||||
python -W ignore -m pip install .[all]
|
||||
python -W ignore -m pip install -r requirements-unit-tests.txt
|
||||
- name: Compare to official api
|
||||
run: |
|
||||
pytest -v tests/test_official/test_official.py --junit-xml=.test_report_official.xml
|
||||
exit $?
|
||||
env:
|
||||
TEST_OFFICIAL: "true"
|
||||
shell: bash --noprofile --norc {0}
|
||||
|
||||
- name: Test Summary
|
||||
id: test_summary
|
||||
uses: test-summary/action@31493c76ec9e7aa675f1585d3ed6f1da69269a86 # v2.4
|
||||
if: always() # always run, even if tests fail
|
||||
with:
|
||||
paths: .test_report_official.xml
|
||||
@@ -0,0 +1,23 @@
|
||||
name: Check Type Completeness
|
||||
on:
|
||||
pull_request:
|
||||
paths:
|
||||
- telegram/**
|
||||
- pyproject.toml
|
||||
- .github/workflows/type_completeness.yml
|
||||
push:
|
||||
branches:
|
||||
- master
|
||||
|
||||
permissions: {}
|
||||
|
||||
jobs:
|
||||
test-type-completeness:
|
||||
name: test-type-completeness
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: Bibo-Joshi/pyright-type-completeness@c85a67ff3c66f51dcbb2d06bfcf4fe83a57d69cc # v1.0.1
|
||||
with:
|
||||
package-name: telegram
|
||||
python-version: 3.12
|
||||
pyright-version: ~=1.1.367
|
||||
@@ -0,0 +1,35 @@
|
||||
name: Check Type Completeness Monthly Run
|
||||
on:
|
||||
schedule:
|
||||
# Run first friday of the month at 03:17 - odd time to spread load on GitHub Actions
|
||||
- cron: '17 3 1-7 * 5'
|
||||
|
||||
permissions: {}
|
||||
|
||||
jobs:
|
||||
test-type-completeness:
|
||||
name: test-type-completeness
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: Bibo-Joshi/pyright-type-completeness@c85a67ff3c66f51dcbb2d06bfcf4fe83a57d69cc # v1.0.1
|
||||
id: pyright-type-completeness
|
||||
with:
|
||||
package-name: telegram
|
||||
python-version: 3.12
|
||||
pyright-version: ~=1.1.367
|
||||
- name: Check Output
|
||||
uses: jannekem/run-python-script-action@bbfca66c612a28f3eeca0ae40e1f810265e2ea68 # v1.7
|
||||
env:
|
||||
TYPE_COMPLETENESS: ${{ steps.pyright-type-completeness.outputs.base-completeness-score }}
|
||||
with:
|
||||
script: |
|
||||
import os
|
||||
completeness = float(os.getenv("TYPE_COMPLETENESS"))
|
||||
|
||||
if completeness >= 1:
|
||||
exit(0)
|
||||
|
||||
text = f"Type Completeness Decreased to {completeness}. ❌"
|
||||
error(text)
|
||||
set_summary(text)
|
||||
exit(1)
|
||||
File diff suppressed because one or more lines are too long
@@ -51,6 +51,8 @@ nosetests.xml
|
||||
coverage.xml
|
||||
*,cover
|
||||
.coveralls.yml
|
||||
.testmondata
|
||||
.testmondata-journal
|
||||
|
||||
# Translations
|
||||
*.mo
|
||||
@@ -65,6 +67,7 @@ docs/_build/
|
||||
# PyBuilder
|
||||
target/
|
||||
.idea/
|
||||
.run/
|
||||
|
||||
# Sublime Text 2
|
||||
*.sublime*
|
||||
@@ -90,3 +93,6 @@ telegram.jpg
|
||||
|
||||
# virtual env
|
||||
venv*
|
||||
|
||||
# environment manager:
|
||||
.mise.toml
|
||||
+38
-37
@@ -1,58 +1,60 @@
|
||||
# Make sure that
|
||||
# * the revs specified here match requirements-dev.txt
|
||||
# * the additional_dependencies here match requirements.txt
|
||||
# Make sure that the additional_dependencies here match pyproject.toml
|
||||
|
||||
ci:
|
||||
autofix_prs: false
|
||||
autoupdate_schedule: monthly
|
||||
# We currently only need this behavior on the v13.x branch were we have the vendored urllib
|
||||
# TODO: Remove once we discontinue v13
|
||||
submodules: true
|
||||
autoupdate_schedule: quarterly
|
||||
autoupdate_commit_msg: 'Bump `pre-commit` Hooks to Latest Versions'
|
||||
|
||||
repos:
|
||||
- repo: https://github.com/psf/black
|
||||
rev: 22.3.0
|
||||
- repo: https://github.com/astral-sh/ruff-pre-commit
|
||||
rev: 'v0.8.6'
|
||||
hooks:
|
||||
- id: ruff
|
||||
name: ruff
|
||||
additional_dependencies:
|
||||
- httpx~=0.27
|
||||
- tornado~=6.4
|
||||
- APScheduler~=3.10.4
|
||||
- cachetools>=5.3.3,<5.5.0
|
||||
- aiolimiter~=1.1,<1.3
|
||||
- repo: https://github.com/psf/black-pre-commit-mirror
|
||||
rev: 24.10.0
|
||||
hooks:
|
||||
- id: black
|
||||
args:
|
||||
- --diff
|
||||
- --check
|
||||
- repo: https://gitlab.com/pycqa/flake8
|
||||
rev: 4.0.1
|
||||
- repo: https://github.com/PyCQA/flake8
|
||||
rev: 7.1.1
|
||||
hooks:
|
||||
- id: flake8
|
||||
- repo: https://github.com/PyCQA/pylint
|
||||
rev: v2.13.9
|
||||
rev: v3.3.3
|
||||
hooks:
|
||||
- id: pylint
|
||||
files: ^(telegram|examples)/.*\.py$
|
||||
args:
|
||||
- --rcfile=setup.cfg
|
||||
# run pylint across multiple cpu cores to speed it up-
|
||||
# https://pylint.pycqa.org/en/latest/user_guide/run.html?#parallel-execution to know more
|
||||
- --jobs=0
|
||||
|
||||
files: ^(?!(tests|docs)).*\.py$
|
||||
additional_dependencies:
|
||||
- httpx~=0.23.0
|
||||
- tornado~=6.1
|
||||
- APScheduler~=3.9.1
|
||||
- cachetools~=5.2.0
|
||||
- httpx~=0.27
|
||||
- tornado~=6.4
|
||||
- APScheduler~=3.10.4
|
||||
- cachetools>=5.3.3,<5.5.0
|
||||
- aiolimiter~=1.1,<1.3
|
||||
- . # this basically does `pip install -e .`
|
||||
- repo: https://github.com/pre-commit/mirrors-mypy
|
||||
rev: v0.961
|
||||
rev: v1.14.1
|
||||
hooks:
|
||||
- id: mypy
|
||||
name: mypy-ptb
|
||||
files: ^telegram/.*\.py$
|
||||
files: ^(?!(tests|examples|docs)).*\.py$
|
||||
additional_dependencies:
|
||||
- types-ujson
|
||||
- types-pytz
|
||||
- types-cryptography
|
||||
- types-cachetools
|
||||
- httpx~=0.23.0
|
||||
- tornado~=6.1
|
||||
- APScheduler~=3.9.1
|
||||
- cachetools~=5.2.0
|
||||
- httpx~=0.27
|
||||
- tornado~=6.4
|
||||
- APScheduler~=3.10.4
|
||||
- cachetools>=5.3.3,<5.5.0
|
||||
- aiolimiter~=1.1,<1.3
|
||||
- . # this basically does `pip install -e .`
|
||||
- id: mypy
|
||||
name: mypy-examples
|
||||
@@ -61,19 +63,18 @@ repos:
|
||||
- --no-strict-optional
|
||||
- --follow-imports=silent
|
||||
additional_dependencies:
|
||||
- tornado~=6.1
|
||||
- APScheduler~=3.9.1
|
||||
- cachetools~=5.2.0
|
||||
- tornado~=6.4
|
||||
- APScheduler~=3.10.4
|
||||
- cachetools>=5.3.3,<5.5.0
|
||||
- . # this basically does `pip install -e .`
|
||||
- repo: https://github.com/asottile/pyupgrade
|
||||
rev: v2.34.0
|
||||
rev: v3.19.1
|
||||
hooks:
|
||||
- id: pyupgrade
|
||||
files: ^(telegram|examples|tests)/.*\.py$
|
||||
args:
|
||||
- --py37-plus
|
||||
- --py39-plus
|
||||
- repo: https://github.com/pycqa/isort
|
||||
rev: 5.10.1
|
||||
rev: 5.13.2
|
||||
hooks:
|
||||
- id: isort
|
||||
name: isort
|
||||
|
||||
+45
-9
@@ -7,20 +7,56 @@ version: 2
|
||||
|
||||
# Build documentation in the docs/ directory with Sphinx
|
||||
sphinx:
|
||||
configuration: docs/source/conf.py
|
||||
configuration: docs/source/conf.py
|
||||
|
||||
# Optionally build your docs in additional formats such as PDF
|
||||
formats:
|
||||
- pdf
|
||||
- pdf
|
||||
|
||||
# Optionally set the version of Python and requirements required to build your docs
|
||||
python:
|
||||
install:
|
||||
- method: pip
|
||||
path: .
|
||||
- requirements: docs/requirements-docs.txt
|
||||
install:
|
||||
- method: pip
|
||||
path: .
|
||||
- requirements: requirements-dev-all.txt
|
||||
|
||||
build:
|
||||
os: ubuntu-20.04
|
||||
tools:
|
||||
python: "3" # latest stable cpython version
|
||||
os: ubuntu-22.04
|
||||
tools:
|
||||
python: "3" # latest stable cpython version
|
||||
jobs:
|
||||
post_build:
|
||||
# Based on https://github.com/readthedocs/readthedocs.org/issues/3242#issuecomment-1410321534
|
||||
# This provides a HTML zip file for download, with the same structure as the hosted website
|
||||
- mkdir --parents $READTHEDOCS_OUTPUT/htmlzip
|
||||
- cp --recursive $READTHEDOCS_OUTPUT/html $READTHEDOCS_OUTPUT/$READTHEDOCS_PROJECT
|
||||
# Hide the "other versions" dropdown. This is a workaround for those versions being shown,
|
||||
# but not being accessible, as they are not built. Also, they hide the actual sidebar menu
|
||||
# that is relevant only on ReadTheDocs.
|
||||
- echo "#furo-readthedocs-versions{display:none}" >> $READTHEDOCS_OUTPUT/$READTHEDOCS_PROJECT/_static/styles/furo-extensions.css
|
||||
- cd $READTHEDOCS_OUTPUT ; zip --recurse-path --symlinks htmlzip/$READTHEDOCS_PROJECT.zip $READTHEDOCS_PROJECT
|
||||
|
||||
search:
|
||||
ranking: # bump up rank of commonly searched pages: (default: 0, values range from -10 to 10)
|
||||
telegram.bot.html: 7
|
||||
telegram.message.html: 3
|
||||
telegram.update.html: 3
|
||||
telegram.user.html: 2
|
||||
telegram.chat.html: 2
|
||||
telegram.ext.application.html: 3
|
||||
telegram.ext.filters.html: 3
|
||||
telegram.ext.callbackcontext.html: 2
|
||||
telegram.ext.inlinekeyboardbutton.html: 1
|
||||
|
||||
telegram.passport*.html: -7
|
||||
|
||||
ignore:
|
||||
- changelog.html
|
||||
- coc.html
|
||||
- bot_methods.html#
|
||||
- bot_methods.html
|
||||
# Defaults
|
||||
- search.html
|
||||
- search/index.html
|
||||
- 404.html
|
||||
- 404/index.html'
|
||||
|
||||
+30
@@ -9,6 +9,8 @@ The current development team includes
|
||||
- `Poolitzer <https://github.com/Poolitzer>`_ (community liaison)
|
||||
- `Shivam <https://github.com/Starry69>`_
|
||||
- `Harshil <https://github.com/harshil21>`_
|
||||
- `Dmitry Kolomatskiy <https://github.com/lemontree210>`_
|
||||
- `Aditya <https://github.com/clot27>`_
|
||||
|
||||
Emeritus maintainers include
|
||||
`Jannes Höke <https://github.com/jh0ker>`_ (`@jh0ker <https://t.me/jh0ker>`_ on Telegram),
|
||||
@@ -19,15 +21,21 @@ Contributors
|
||||
|
||||
The following wonderful people contributed directly or indirectly to this project:
|
||||
|
||||
- `Abdelrahman <https://github.com/aelkheir>`_
|
||||
- `Abshar <https://github.com/abxhr>`_
|
||||
- `Abubakar Alaya <https://github.com/Ecode2>`_
|
||||
- `Alateas <https://github.com/alateas>`_
|
||||
- `Ales Dokshanin <https://github.com/alesdokshanin>`_
|
||||
- `Alexandre <https://github.com/xTudoS>`_
|
||||
- `Alizia <https://github.com/thefunkycat>`_
|
||||
- `Ambro17 <https://github.com/Ambro17>`_
|
||||
- `Andrej Zhilenkov <https://github.com/Andrej730>`_
|
||||
- `Anton Tagunov <https://github.com/anton-tagunov>`_
|
||||
- `Anya Marcano <https://github.com/AnyaMarcanito>`
|
||||
- `Avanatiker <https://github.com/Avanatiker>`_
|
||||
- `Balduro <https://github.com/Balduro>`_
|
||||
- `Bibo-Joshi <https://github.com/Bibo-Joshi>`_
|
||||
- `Biruk Alamirew <https://github.com/BAcode-X>`_
|
||||
- `bimmlerd <https://github.com/bimmlerd>`_
|
||||
- `cyc8 <https://github.com/cyc8>`_
|
||||
- `d-qoi <https://github.com/d-qoi>`_
|
||||
@@ -51,10 +59,14 @@ The following wonderful people contributed directly or indirectly to this projec
|
||||
- `gamgi <https://github.com/gamgi>`_
|
||||
- `Gauthamram Ravichandran <https://github.com/GauthamramRavichandran>`_
|
||||
- `Harshil <https://github.com/harshil21>`_
|
||||
- `Henry Galue <https://github.com/henryg311>`
|
||||
- `Hugo Damer <https://github.com/HakimusGIT>`_
|
||||
- `ihoru <https://github.com/ihoru>`_
|
||||
- `Iulian Onofrei <https://github.com/revolter>`_
|
||||
- `Jainam Oswal <https://github.com/jainamoswal>`_
|
||||
- `Jasmin Bom <https://github.com/jsmnbom>`_
|
||||
- `JASON0916 <https://github.com/JASON0916>`_
|
||||
- `Jeamhowards Montiel <https://github.com/Jeam-zx>`
|
||||
- `jeffffc <https://github.com/jeffffc>`_
|
||||
- `Jelle Besseling <https://github.com/pingiun>`_
|
||||
- `jh0ker <https://github.com/jh0ker>`_
|
||||
@@ -63,16 +75,26 @@ The following wonderful people contributed directly or indirectly to this projec
|
||||
- `Joscha Götzer <https://github.com/Rostgnom>`_
|
||||
- `jossalgon <https://github.com/jossalgon>`_
|
||||
- `JRoot3D <https://github.com/JRoot3D>`_
|
||||
- `Juan Cuevas <https://github.com/cuevasrja>`
|
||||
- `kenjitagawa <https://github.com/kenjitagawa>`_
|
||||
- `kennethcheo <https://github.com/kennethcheo>`_
|
||||
- `Kirill Vasin <https://github.com/vasinkd>`_
|
||||
- `Kjwon15 <https://github.com/kjwon15>`_
|
||||
- `Li-aung Yip <https://github.com/LiaungYip>`_
|
||||
- `Loo Zheng Yuan <https://github.com/loozhengyuan>`_
|
||||
- `LRezende <https://github.com/lrezende>`_
|
||||
- `Luca Bellanti <https://github.com/Trifase>`_
|
||||
- `Lucas Molinari <https://github.com/lucasmolinari>`_
|
||||
- `Luis Pérez <https://github.com/nemacysts>`_
|
||||
- `macrojames <https://github.com/macrojames>`_
|
||||
- `Matheus Lemos <https://github.com/mlemosf>`_
|
||||
- `Michael Dix <https://github.com/Eisberge>`_
|
||||
- `Michael Elovskikh <https://github.com/wronglink>`_
|
||||
- `Miguel C. R. <https://github.com/MiguelX413>`_
|
||||
- `Miguel Salomon <https://github.com/Migueldsc12>`
|
||||
- `miles <https://github.com/miles170>`_
|
||||
- `Mischa Krüger <https://github.com/Makman2>`_
|
||||
- `Mohd Yusuf <https://github.com/mohdyusuf2312>`_
|
||||
- `naveenvhegde <https://github.com/naveenvhegde>`_
|
||||
- `neurrone <https://github.com/neurrone>`_
|
||||
- `NikitaPirate <https://github.com/NikitaPirate>`_
|
||||
@@ -83,9 +105,11 @@ The following wonderful people contributed directly or indirectly to this projec
|
||||
- `Oleg Sushchenko <https://github.com/feuillemorte>`_
|
||||
- `Or Bin <https://github.com/OrBin>`_
|
||||
- `overquota <https://github.com/overquota>`_
|
||||
- `Pablo Martinez <https://github.com/elpekenin>`_
|
||||
- `Paradox <https://github.com/paradox70>`_
|
||||
- `Patrick Hofmann <https://github.com/PH89>`_
|
||||
- `Paul Larsen <https://github.com/PaulSonOfLars>`_
|
||||
- `Pawan <https://github.com/pawanrai9999>`_
|
||||
- `Pieter Schutz <https://github.com/eldinnie>`_
|
||||
- `Piraty <https://github.com/piraty>`_
|
||||
- `Poolitzer <https://github.com/Poolitzer>`_
|
||||
@@ -93,9 +117,13 @@ The following wonderful people contributed directly or indirectly to this projec
|
||||
- `Rahiel Kasim <https://github.com/rahiel>`_
|
||||
- `Riko Naka <https://github.com/rikonaka>`_
|
||||
- `Rizlas <https://github.com/rizlas>`_
|
||||
- Snehashish Biswas
|
||||
- `Sahil Sharma <https://github.com/sahilsharma811>`_
|
||||
- `Sam Mosleh <https://github.com/sam-mosleh>`_
|
||||
- `Sascha <https://github.com/saschalalala>`_
|
||||
- `Shelomentsev D <https://github.com/shelomentsevd>`_
|
||||
- `Shivam Saini <https://github.com/shivamsn97>`_
|
||||
- `Siloé Garcez <https://github.com/roast-lord>`_
|
||||
- `Simon Schürrle <https://github.com/SitiSchu>`_
|
||||
- `sooyhwang <https://github.com/sooyhwang>`_
|
||||
- `syntx <https://github.com/syntx>`_
|
||||
@@ -107,7 +135,9 @@ The following wonderful people contributed directly or indirectly to this projec
|
||||
- `Vorobjev Simon <https://github.com/simonvorobjev>`_
|
||||
- `Wagner Macedo <https://github.com/wagnerluis1982>`_
|
||||
- `wjt <https://github.com/wjt>`_
|
||||
- `Wonseok Oh <https://github.com/marinelay>`_
|
||||
- `Yaw Danso <https://github.com/dglitxh>`_
|
||||
- `Yao Kuan <https://github.com/thatguylah>`_
|
||||
- `zeroone2numeral2 <https://github.com/zeroone2numeral2>`_
|
||||
- `zeshuaro <https://github.com/zeshuaro>`_
|
||||
- `zpavloudis <https://github.com/zpavloudis>`_
|
||||
|
||||
-2241
File diff suppressed because it is too large
Load Diff
@@ -1 +0,0 @@
|
||||
include LICENSE LICENSE.lesser Makefile requirements.txt README_RAW.rst telegram/py.typed
|
||||
+78
-43
@@ -1,6 +1,3 @@
|
||||
..
|
||||
Make sure to apply any changes to this file to README_RAW.rst as well!
|
||||
|
||||
.. image:: https://raw.githubusercontent.com/python-telegram-bot/logos/master/logo-text/png/ptb-logo-text_768.png
|
||||
:align: center
|
||||
:target: https://python-telegram-bot.org
|
||||
@@ -14,9 +11,9 @@
|
||||
:target: https://pypi.org/project/python-telegram-bot/
|
||||
:alt: Supported Python versions
|
||||
|
||||
.. image:: https://img.shields.io/badge/Bot%20API-6.1-blue?logo=telegram
|
||||
.. image:: https://img.shields.io/badge/Bot%20API-8.3-blue?logo=telegram
|
||||
:target: https://core.telegram.org/bots/api-changelog
|
||||
:alt: Supported Bot API versions
|
||||
:alt: Supported Bot API version
|
||||
|
||||
.. image:: https://img.shields.io/pypi/dm/python-telegram-bot
|
||||
:target: https://pypistats.org/packages/python-telegram-bot
|
||||
@@ -30,7 +27,7 @@
|
||||
:target: https://www.gnu.org/licenses/lgpl-3.0.html
|
||||
:alt: LGPLv3 License
|
||||
|
||||
.. image:: https://github.com/python-telegram-bot/python-telegram-bot/workflows/GitHub%20Actions/badge.svg
|
||||
.. image:: https://github.com/python-telegram-bot/python-telegram-bot/actions/workflows/unit_tests.yml/badge.svg?branch=master
|
||||
:target: https://github.com/python-telegram-bot/python-telegram-bot/
|
||||
:alt: Github Actions workflow
|
||||
|
||||
@@ -46,10 +43,6 @@
|
||||
:target: https://app.codacy.com/gh/python-telegram-bot/python-telegram-bot/dashboard
|
||||
:alt: Code quality: Codacy
|
||||
|
||||
.. image:: https://deepsource.io/gh/python-telegram-bot/python-telegram-bot.svg/?label=active+issues
|
||||
:target: https://deepsource.io/gh/python-telegram-bot/python-telegram-bot/?ref=repository-badge
|
||||
:alt: Code quality: DeepSource
|
||||
|
||||
.. image:: https://results.pre-commit.ci/badge/github/python-telegram-bot/python-telegram-bot/master.svg
|
||||
:target: https://results.pre-commit.ci/latest/github/python-telegram-bot/python-telegram-bot/master
|
||||
:alt: pre-commit.ci status
|
||||
@@ -73,30 +66,36 @@ We have a vibrant community of developers helping each other in our `Telegram gr
|
||||
*Stay tuned for library updates and new releases on our* `Telegram Channel <https://telegram.me/pythontelegrambotchannel>`_.
|
||||
|
||||
Introduction
|
||||
============
|
||||
------------
|
||||
|
||||
This library provides a pure Python, asynchronous interface for the
|
||||
`Telegram Bot API <https://core.telegram.org/bots/api>`_.
|
||||
It's compatible with Python versions **3.7+**.
|
||||
It's compatible with Python versions **3.9+**.
|
||||
|
||||
In addition to the pure API implementation, this library features a number of high-level classes to
|
||||
In addition to the pure API implementation, this library features several convenience methods and shortcuts as well as a number of high-level classes to
|
||||
make the development of bots easy and straightforward. These classes are contained in the
|
||||
``telegram.ext`` submodule.
|
||||
|
||||
A pure API implementation *without* ``telegram.ext`` is available as the standalone package ``python-telegram-bot-raw``. `See here for details. <https://github.com/python-telegram-bot/python-telegram-bot/blob/master/README_RAW.rst>`_
|
||||
|
||||
Note
|
||||
----
|
||||
|
||||
Installing both ``python-telegram-bot`` and ``python-telegram-bot-raw`` in conjunction will result in undesired side-effects, so only install *one* of both.
|
||||
After installing_ the library, be sure to check out the section on `working with PTB`_.
|
||||
|
||||
Telegram API support
|
||||
====================
|
||||
~~~~~~~~~~~~~~~~~~~~
|
||||
|
||||
All types and methods of the Telegram Bot API **6.1** are supported.
|
||||
All types and methods of the Telegram Bot API **8.3** are natively supported by this library.
|
||||
In addition, Bot API functionality not yet natively included can still be used as described `in our wiki <https://github.com/python-telegram-bot/python-telegram-bot/wiki/Bot-API-Forward-Compatibility>`_.
|
||||
|
||||
Notable Features
|
||||
~~~~~~~~~~~~~~~~
|
||||
|
||||
- `Fully asynchronous <https://github.com/python-telegram-bot/python-telegram-bot/wiki/Concurrency>`_
|
||||
- Convenient shortcut methods, e.g. `Message.reply_text <https://docs.python-telegram-bot.org/en/stable/telegram.message.html#telegram.Message.reply_text>`_
|
||||
- `Fully annotated with static type hints <https://github.com/python-telegram-bot/python-telegram-bot/wiki/Type-Checking>`_
|
||||
- `Customizable and extendable interface <https://github.com/python-telegram-bot/python-telegram-bot/wiki/Architecture>`_
|
||||
- Seamless integration with `webhooks <https://github.com/python-telegram-bot/python-telegram-bot/wiki/Webhooks>`_ and `polling <https://docs.python-telegram-bot.org/en/stable/telegram.ext.application.html#telegram.ext.Application.run_polling>`_
|
||||
- `Comprehensive documentation and examples <#working-with-ptb>`_
|
||||
|
||||
Installing
|
||||
==========
|
||||
----------
|
||||
|
||||
You can install or upgrade ``python-telegram-bot`` via
|
||||
|
||||
@@ -112,41 +111,75 @@ You can also install ``python-telegram-bot`` from source, though this is usually
|
||||
|
||||
$ git clone https://github.com/python-telegram-bot/python-telegram-bot
|
||||
$ cd python-telegram-bot
|
||||
$ python setup.py install
|
||||
$ pip install build
|
||||
$ python -m build
|
||||
|
||||
Verifying Releases
|
||||
~~~~~~~~~~~~~~~~~~
|
||||
|
||||
To enable you to verify that a release file that you downloaded was indeed provided by the ``python-telegram-bot`` team, we have taken the following measures.
|
||||
|
||||
Starting with v21.4, all releases are signed via `sigstore <https://www.sigstore.dev>`_.
|
||||
The corresponding signature files are uploaded to the `GitHub releases page`_.
|
||||
To verify the signature, please install the `sigstore Python client <https://pypi.org/project/sigstore/>`_ and follow the instructions for `verifying signatures from GitHub Actions <https://github.com/sigstore/sigstore-python?tab=readme-ov-file>`_. As input for the ``--repository`` parameter, please use the value ``python-telegram-bot/python-telegram-bot``.
|
||||
|
||||
Earlier releases are signed with a GPG key.
|
||||
The signatures are uploaded to both the `GitHub releases page`_ and the `PyPI project <https://pypi.org/project/python-telegram-bot/>`_ and end with a suffix ``.asc``.
|
||||
Please find the public keys `here <https://github.com/python-telegram-bot/python-telegram-bot/tree/master/public_keys>`_.
|
||||
The keys are named in the format ``<first_version>-<last_version>.gpg``.
|
||||
|
||||
In addition, the GitHub release page also contains the sha1 hashes of the release files in the files with the suffix ``.sha1``.
|
||||
|
||||
Dependencies & Their Versions
|
||||
-----------------------------
|
||||
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
|
||||
``python-telegram-bot`` tries to use as few 3rd party dependencies as possible.
|
||||
However, for some features using a 3rd party library is more sane than implementing the functionality again.
|
||||
The dependencies are:
|
||||
As these features are *optional*, the corresponding 3rd party dependencies are not installed by default.
|
||||
Instead, they are listed as optional dependencies.
|
||||
This allows to avoid unnecessary dependency conflicts for users who don't need the optional features.
|
||||
|
||||
* `httpx ~= 0.23.0 <https://www.python-httpx.org>`_ for ``telegram.request.HTTPXRequest``, the default networking backend
|
||||
* `tornado~=6.1 <https://www.tornadoweb.org/en/stable/>`_ for ``telegram.ext.Updater.start_webhook``
|
||||
* `cachetools~=5.2.0 <https://cachetools.readthedocs.io/en/latest/>`_ for ``telegram.ext.CallbackDataCache``
|
||||
* `APScheduler~=3.9.1 <https://apscheduler.readthedocs.io/en/3.x/>`_ for ``telegram.ext.JobQueue``
|
||||
The only required dependency is `httpx ~= 0.27 <https://www.python-httpx.org>`_ for
|
||||
``telegram.request.HTTPXRequest``, the default networking backend.
|
||||
|
||||
``python-telegram-bot`` is most useful when used along with additional libraries.
|
||||
To minimize dependency conflicts, we try to be liberal in terms of version requirements on the dependencies.
|
||||
To minimize dependency conflicts, we try to be liberal in terms of version requirements on the (optional) dependencies.
|
||||
On the other hand, we have to ensure stability of ``python-telegram-bot``, which is why we do apply version bounds.
|
||||
If you encounter dependency conflicts due to these bounds, feel free to reach out.
|
||||
|
||||
Optional Dependencies
|
||||
---------------------
|
||||
#####################
|
||||
|
||||
PTB can be installed with optional dependencies:
|
||||
|
||||
* ``pip install python-telegram-bot[passport]`` installs the `cryptography>=3.0 <https://cryptography.io/en/stable>`_ library. Use this, if you want to use Telegram Passport related functionality.
|
||||
* ``pip install python-telegram-bot[socks]`` installs ``httpx[socks]``. Use this, if you want to work behind a Socks5 server.
|
||||
* ``pip install "python-telegram-bot[passport]"`` installs the `cryptography>=39.0.1 <https://cryptography.io/en/stable>`_ library. Use this, if you want to use Telegram Passport related functionality.
|
||||
* ``pip install "python-telegram-bot[socks]"`` installs `httpx[socks] <https://www.python-httpx.org/#dependencies>`_. Use this, if you want to work behind a Socks5 server.
|
||||
* ``pip install "python-telegram-bot[http2]"`` installs `httpx[http2] <https://www.python-httpx.org/#dependencies>`_. Use this, if you want to use HTTP/2.
|
||||
* ``pip install "python-telegram-bot[rate-limiter]"`` installs `aiolimiter~=1.1,<1.3 <https://aiolimiter.readthedocs.io/en/stable/>`_. Use this, if you want to use ``telegram.ext.AIORateLimiter``.
|
||||
* ``pip install "python-telegram-bot[webhooks]"`` installs the `tornado~=6.4 <https://www.tornadoweb.org/en/stable/>`_ library. Use this, if you want to use ``telegram.ext.Updater.start_webhook``/``telegram.ext.Application.run_webhook``.
|
||||
* ``pip install "python-telegram-bot[callback-data]"`` installs the `cachetools>=5.3.3,<5.6.0 <https://cachetools.readthedocs.io/en/latest/>`_ library. Use this, if you want to use `arbitrary callback_data <https://github.com/python-telegram-bot/python-telegram-bot/wiki/Arbitrary-callback_data>`_.
|
||||
* ``pip install "python-telegram-bot[job-queue]"`` installs the `APScheduler>=3.10.4,<3.12.0 <https://apscheduler.readthedocs.io/en/3.x/>`_ library. Use this, if you want to use the ``telegram.ext.JobQueue``.
|
||||
|
||||
To install multiple optional dependencies, separate them by commas, e.g. ``pip install "python-telegram-bot[socks,webhooks]"``.
|
||||
|
||||
Additionally, two shortcuts are provided:
|
||||
|
||||
* ``pip install "python-telegram-bot[all]"`` installs all optional dependencies.
|
||||
* ``pip install "python-telegram-bot[ext]"`` installs all optional dependencies that are related to ``telegram.ext``, i.e. ``[rate-limiter, webhooks, callback-data, job-queue]``.
|
||||
|
||||
Working with PTB
|
||||
----------------
|
||||
|
||||
Once you have installed the library, you can begin working with it - so let's get started!
|
||||
|
||||
Quick Start
|
||||
===========
|
||||
~~~~~~~~~~~
|
||||
|
||||
Our Wiki contains an `Introduction to the API <https://github.com/python-telegram-bot/python-telegram-bot/wiki/Introduction-to-the-API>`_ explaining how the pure Bot API can be accessed via ``python-telegram-bot``.
|
||||
Moreover, the `Tutorial: Your first Bot <https://github.com/python-telegram-bot/python-telegram-bot/wiki/Extensions-%E2%80%93-Your-first-Bot>`_ gives an introduction on how chatbots can be easily programmed with the help of the ``telegram.ext`` module.
|
||||
Moreover, the `Tutorial: Your first Bot <https://github.com/python-telegram-bot/python-telegram-bot/wiki/Extensions---Your-first-Bot>`_ gives an introduction on how chatbots can be easily programmed with the help of the ``telegram.ext`` module.
|
||||
|
||||
Resources
|
||||
=========
|
||||
~~~~~~~~~
|
||||
|
||||
- The `package documentation <https://docs.python-telegram-bot.org/>`_ is the technical reference for ``python-telegram-bot``.
|
||||
It contains descriptions of all available classes, modules, methods and arguments as well as the `changelog <https://docs.python-telegram-bot.org/changelog.html>`_.
|
||||
@@ -157,7 +190,7 @@ Resources
|
||||
- The `official Telegram Bot API documentation <https://core.telegram.org/bots/api>`_ is of course always worth a read.
|
||||
|
||||
Getting help
|
||||
============
|
||||
~~~~~~~~~~~~
|
||||
|
||||
If the resources mentioned above don't answer your questions or simply overwhelm you, there are several ways of getting help.
|
||||
|
||||
@@ -168,7 +201,7 @@ If the resources mentioned above don't answer your questions or simply overwhelm
|
||||
3. You can even ask for help on Stack Overflow using the `python-telegram-bot tag <https://stackoverflow.com/questions/tagged/python-telegram-bot>`_.
|
||||
|
||||
Concurrency
|
||||
===========
|
||||
~~~~~~~~~~~
|
||||
|
||||
Since v20.0, ``python-telegram-bot`` is built on top of Pythons ``asyncio`` module.
|
||||
Because ``asyncio`` is in general single-threaded, ``python-telegram-bot`` does currently not aim to be thread-safe.
|
||||
@@ -181,20 +214,22 @@ Noteworthy parts of ``python-telegram-bots`` API that are likely to cause issues
|
||||
* all classes in the ``telegram.ext.filters`` module that allow to add/remove allowed users/chats at runtime
|
||||
|
||||
Contributing
|
||||
============
|
||||
------------
|
||||
|
||||
Contributions of all sizes are welcome.
|
||||
Please review our `contribution guidelines <https://github.com/python-telegram-bot/python-telegram-bot/blob/master/.github/CONTRIBUTING.rst>`_ to get started.
|
||||
You can also help by `reporting bugs or feature requests <https://github.com/python-telegram-bot/python-telegram-bot/issues/new>`_.
|
||||
You can also help by `reporting bugs or feature requests <https://github.com/python-telegram-bot/python-telegram-bot/issues/new/choose>`_.
|
||||
|
||||
Donating
|
||||
========
|
||||
--------
|
||||
Occasionally we are asked if we accept donations to support the development.
|
||||
While we appreciate the thought, maintaining PTB is our hobby, and we have almost no running costs for it. We therefore have nothing set up to accept donations.
|
||||
If you still want to donate, we kindly ask you to donate to another open source project/initiative of your choice instead.
|
||||
|
||||
License
|
||||
=======
|
||||
-------
|
||||
|
||||
You may copy, distribute and modify the software provided that modifications are described and licensed for free under `LGPL-3 <https://www.gnu.org/licenses/lgpl-3.0.html>`_.
|
||||
Derivatives works (including modifications or anything statically linked to the library) can only be redistributed under LGPL-3, but applications that use the library don't have to be.
|
||||
Derivative works (including modifications or anything statically linked to the library) can only be redistributed under LGPL-3, but applications that use the library don't have to be.
|
||||
|
||||
.. _`GitHub releases page`: https://github.com/python-telegram-bot/python-telegram-bot/releases
|
||||
|
||||
-190
@@ -1,190 +0,0 @@
|
||||
..
|
||||
Make sure to apply any changes to this file to README.rst as well!
|
||||
|
||||
.. image:: https://github.com/python-telegram-bot/logos/blob/master/logo-text/png/ptb-raw-logo-text_768.png?raw=true
|
||||
:align: center
|
||||
:target: https://python-telegram-bot.org
|
||||
:alt: python-telegram-bot-raw Logo
|
||||
|
||||
.. image:: https://img.shields.io/pypi/v/python-telegram-bot-raw.svg
|
||||
:target: https://pypi.org/project/python-telegram-bot-raw/
|
||||
:alt: PyPi Package Version
|
||||
|
||||
.. image:: https://img.shields.io/pypi/pyversions/python-telegram-bot-raw.svg
|
||||
:target: https://pypi.org/project/python-telegram-bot-raw/
|
||||
:alt: Supported Python versions
|
||||
|
||||
.. image:: https://img.shields.io/badge/Bot%20API-6.1-blue?logo=telegram
|
||||
:target: https://core.telegram.org/bots/api-changelog
|
||||
:alt: Supported Bot API versions
|
||||
|
||||
.. image:: https://img.shields.io/pypi/dm/python-telegram-bot-raw
|
||||
:target: https://pypistats.org/packages/python-telegram-bot-raw
|
||||
:alt: PyPi Package Monthly Download
|
||||
|
||||
.. image:: https://readthedocs.org/projects/python-telegram-bot/badge/?version=stable
|
||||
:target: https://docs.python-telegram-bot.org/
|
||||
:alt: Documentation Status
|
||||
|
||||
.. image:: https://img.shields.io/pypi/l/python-telegram-bot-raw.svg
|
||||
:target: https://www.gnu.org/licenses/lgpl-3.0.html
|
||||
:alt: LGPLv3 License
|
||||
|
||||
.. image:: https://github.com/python-telegram-bot/python-telegram-bot/workflows/GitHub%20Actions/badge.svg
|
||||
:target: https://github.com/python-telegram-bot/python-telegram-bot/
|
||||
:alt: Github Actions workflow
|
||||
|
||||
.. image:: https://app.codecov.io/gh/python-telegram-bot/python-telegram-bot
|
||||
:target: https://app.codecov.io/gh/python-telegram-bot/python-telegram-bot
|
||||
:alt: Code coverage
|
||||
|
||||
.. image:: https://isitmaintained.com/badge/resolution/python-telegram-bot/python-telegram-bot.svg
|
||||
:target: https://isitmaintained.com/project/python-telegram-bot/python-telegram-bot
|
||||
:alt: Median time to resolve an issue
|
||||
|
||||
.. image:: https://api.codacy.com/project/badge/Grade/99d901eaa09b44b4819aec05c330c968
|
||||
:target: https://app.codacy.com/gh/python-telegram-bot/python-telegram-bot/dashboard
|
||||
:alt: Code quality: Codacy
|
||||
|
||||
.. image:: https://deepsource.io/gh/python-telegram-bot/python-telegram-bot.svg/?label=active+issues
|
||||
:target: https://deepsource.io/gh/python-telegram-bot/python-telegram-bot/?ref=repository-badge
|
||||
:alt: Code quality: DeepSource
|
||||
|
||||
.. image:: https://results.pre-commit.ci/badge/github/python-telegram-bot/python-telegram-bot/master.svg
|
||||
:target: https://results.pre-commit.ci/latest/github/python-telegram-bot/python-telegram-bot/master
|
||||
:alt: pre-commit.ci status
|
||||
|
||||
.. image:: https://img.shields.io/badge/code%20style-black-000000.svg
|
||||
:target: https://github.com/psf/black
|
||||
:alt: Code Style: Black
|
||||
|
||||
.. image:: https://img.shields.io/badge/Telegram-Channel-blue.svg?logo=telegram
|
||||
:target: https://t.me/pythontelegrambotchannel
|
||||
:alt: Telegram Channel
|
||||
|
||||
.. image:: https://img.shields.io/badge/Telegram-Group-blue.svg?logo=telegram
|
||||
:target: https://telegram.me/pythontelegrambotgroup
|
||||
:alt: Telegram Group
|
||||
|
||||
We have made you a wrapper you can't refuse
|
||||
|
||||
We have a vibrant community of developers helping each other in our `Telegram group <https://telegram.me/pythontelegrambotgroup>`_. Join us!
|
||||
|
||||
*Stay tuned for library updates and new releases on our* `Telegram Channel <https://telegram.me/pythontelegrambotchannel>`_.
|
||||
|
||||
Introduction
|
||||
============
|
||||
|
||||
This library provides a pure Python, asynchronous interface for the
|
||||
`Telegram Bot API <https://core.telegram.org/bots/api>`_.
|
||||
It's compatible with Python versions **3.7+**.
|
||||
|
||||
``python-telegram-bot-raw`` is part of the `python-telegram-bot <https://python-telegram-bot.org>`_ ecosystem and provides the pure API functionality extracted from PTB. It therefore does not have independent release schedules, changelogs or documentation.
|
||||
|
||||
Note
|
||||
----
|
||||
|
||||
Installing both ``python-telegram-bot`` and ``python-telegram-bot-raw`` in conjunction will result in undesired side-effects, so only install *one* of both.
|
||||
|
||||
Telegram API support
|
||||
====================
|
||||
|
||||
All types and methods of the Telegram Bot API **6.1** are supported.
|
||||
|
||||
Installing
|
||||
==========
|
||||
|
||||
You can install or upgrade ``python-telegram-bot`` via
|
||||
|
||||
.. code:: shell
|
||||
|
||||
$ pip install python-telegram-bot-raw --upgrade
|
||||
|
||||
To install a pre-release, use the ``--pre`` `flag <https://pip.pypa.io/en/stable/cli/pip_install/#cmdoption-pre>`_ in addition.
|
||||
|
||||
You can also install ``python-telegram-bot-raw`` from source, though this is usually not necessary.
|
||||
|
||||
.. code:: shell
|
||||
|
||||
$ git clone https://github.com/python-telegram-bot/python-telegram-bot
|
||||
$ cd python-telegram-bot
|
||||
$ python setup-raw.py install
|
||||
|
||||
Note
|
||||
----
|
||||
|
||||
Installing the ``.tar.gz`` archive available on PyPi directly via ``pip`` will *not* work as expected, as ``pip`` does not recognize that it should use ``setup-raw.py`` instead of ``setup.py``.
|
||||
|
||||
Dependencies & Their Versions
|
||||
-----------------------------
|
||||
|
||||
``python-telegram-bot`` tries to use as few 3rd party dependencies as possible.
|
||||
However, for some features using a 3rd party library is more sane than implementing the functionality again.
|
||||
The dependencies are:
|
||||
|
||||
* `httpx ~= 0.23.0 <https://www.python-httpx.org>`_ for ``telegram.request.HTTPXRequest``, the default networking backend
|
||||
|
||||
``python-telegram-bot`` is most useful when used along with additional libraries.
|
||||
To minimize dependency conflicts, we try to be liberal in terms of version requirements on the dependencies.
|
||||
On the other hand, we have to ensure stability of ``python-telegram-bot``, which is why we do apply version bounds.
|
||||
If you encounter dependency conflicts due to these bounds, feel free to reach out.
|
||||
|
||||
Optional Dependencies
|
||||
---------------------
|
||||
|
||||
``python-telegram-bot-raw`` can be installed with optional dependencies:
|
||||
|
||||
* ``pip install python-telegram-bot[passport]`` installs the `cryptography <https://cryptography.io/en/stable>`_ library. Use this, if you want to use Telegram Passport related functionality.
|
||||
* ``pip install python-telegram-bot[socks]`` installs the `PySocks <https://pypi.org/project/PySocks/>`_ library. Use this, if you want to work behind a Socks5 server.
|
||||
|
||||
Quick Start
|
||||
===========
|
||||
|
||||
Our Wiki contains an `Introduction to the API <https://github.com/python-telegram-bot/python-telegram-bot/wiki/Introduction-to-the-API>`_ explaining how the pure Bot API can be accessed via ``python-telegram-bot``.
|
||||
|
||||
Resources
|
||||
=========
|
||||
|
||||
- The `package documentation <https://docs.python-telegram-bot.org/>`_ is the technical reference for ``python-telegram-bot``.
|
||||
It contains descriptions of all available classes, modules, methods and arguments as well as the `changelog <https://docs.python-telegram-bot.org/changelog.html>`_.
|
||||
- The `wiki <https://github.com/python-telegram-bot/python-telegram-bot/wiki/>`_ is home to number of more elaborate introductions of the different features of ``python-telegram-bot`` and other useful resources that go beyond the technical documentation.
|
||||
- Our `examples section <https://docs.python-telegram-bot.org/examples.html>`_ contains several examples that showcase the different features of both the Bot API and ``python-telegram-bot``.
|
||||
Even if it is not your approach for learning, please take a look at ``echobot.py``. It is the de facto base for most of the bots out there.
|
||||
The code for these examples is released to the public domain, so you can start by grabbing the code and building on top of it.
|
||||
- The `official Telegram Bot API documentation <https://core.telegram.org/bots/api>`_ is of course always worth a read.
|
||||
|
||||
Getting help
|
||||
============
|
||||
|
||||
If the resources mentioned above don't answer your questions or simply overwhelm you, there are several ways of getting help.
|
||||
|
||||
1. We have a vibrant community of developers helping each other in our `Telegram group <https://telegram.me/pythontelegrambotgroup>`_. Join us! Asking a question here is often the quickest way to get a pointer in the right direction.
|
||||
|
||||
2. Ask questions by opening `a discussion <https://github.com/python-telegram-bot/python-telegram-bot/discussions/new>`_.
|
||||
|
||||
3. You can even ask for help on Stack Overflow using the `python-telegram-bot tag <https://stackoverflow.com/questions/tagged/python-telegram-bot>`_.
|
||||
|
||||
Concurrency
|
||||
===========
|
||||
|
||||
Since v20.0, ``python-telegram-bot`` is built on top of Pythons ``asyncio`` module.
|
||||
Because ``asyncio`` is in general single-threaded, ``python-telegram-bot`` does currently not aim to be thread-safe.
|
||||
|
||||
Contributing
|
||||
============
|
||||
|
||||
Contributions of all sizes are welcome.
|
||||
Please review our `contribution guidelines <https://github.com/python-telegram-bot/python-telegram-bot/blob/master/.github/CONTRIBUTING.rst>`_ to get started.
|
||||
You can also help by `reporting bugs or feature requests <https://github.com/python-telegram-bot/python-telegram-bot/issues/new>`_.
|
||||
|
||||
Donating
|
||||
========
|
||||
Occasionally we are asked if we accept donations to support the development.
|
||||
While we appreciate the thought, maintaining PTB is our hobby, and we have almost no running costs for it. We therefore have nothing set up to accept donations.
|
||||
If you still want to donate, we kindly ask you to donate to another open source project/initiative of your choice instead.
|
||||
|
||||
License
|
||||
=======
|
||||
|
||||
You may copy, distribute and modify the software provided that modifications are described and licensed for free under `LGPL-3 <https://www.gnu.org/licenses/lgpl-3.0.html>`_.
|
||||
Derivatives works (including modifications or anything statically linked to the library) can only be redistributed under LGPL-3, but applications that use the library don't have to be.
|
||||
@@ -0,0 +1,19 @@
|
||||
breaking = """This release removes all functionality that was deprecated in v20.x. This is in line with our :ref:`stability policy <stability-policy>`.
|
||||
This includes the following changes:
|
||||
|
||||
- Removed ``filters.CHAT`` (all messages have an associated chat) and ``filters.StatusUpdate.USER_SHARED`` (use ``filters.StatusUpdate.USERS_SHARED`` instead).
|
||||
- Removed ``Defaults.disable_web_page_preview`` and ``Defaults.quote``. Use ``Defaults.link_preview_options`` and ``Defaults.do_quote`` instead.
|
||||
- Removed ``ApplicationBuilder.(get_updates_)proxy_url`` and ``HTTPXRequest.proxy_url``. Use ``ApplicationBuilder.(get_updates_)proxy`` and ``HTTPXRequest.proxy`` instead.
|
||||
- Removed the ``*_timeout`` arguments of ``Application.run_polling`` and ``Updater.start_webhook``. Instead, specify the values via ``ApplicationBuilder.get_updates_*_timeout``.
|
||||
- Removed ``constants.InlineQueryLimit.MIN_SWITCH_PM_TEXT_LENGTH``. Use ``constants.InlineQueryResultsButtonLimit.MAX_START_PARAMETER_LENGTH`` instead.
|
||||
- Removed the argument ``quote`` of ``Message.reply_*``. Use ``do_quote`` instead.
|
||||
- Removed the superfluous ``EncryptedPassportElement.credentials`` without replacement.
|
||||
- Changed attribute value of ``PassportFile.file_date`` from :obj:`int` to :class:`datetime.datetime`. Make sure to adjust your code accordingly.
|
||||
- Changed the attribute value of ``PassportElementErrors.file_hashes`` from :obj:`list` to :obj:`tuple`. Make sure to adjust your code accordingly.
|
||||
- Make ``BaseRequest.read_timeout`` an abstract property. If you subclass ``BaseRequest``, you need to implement this property.
|
||||
- The default value for ``write_timeout`` now defaults to ``DEFAULT_NONE`` also for bot methods that send media. Previously, it was ``20``. If you subclass ``BaseRequest``, make sure to use your desired write timeout if ``RequestData.multipart_data`` is set.
|
||||
"""
|
||||
[[pull_requests]]
|
||||
uid = "4671"
|
||||
author_uid = "Bibo-Joshi"
|
||||
closes_threads = ["4659"]
|
||||
@@ -0,0 +1,5 @@
|
||||
documentation = "Add `chango <https://chango.readthedocs.io/stable/>`_ As Changelog Management Tool"
|
||||
[[pull_requests]]
|
||||
uid = "4672"
|
||||
author_uid = "Bibo-Joshi"
|
||||
closes_threads = ["4321"]
|
||||
@@ -0,0 +1,5 @@
|
||||
internal = "Bump github/codeql-action from 3.28.8 to 3.28.10"
|
||||
[[pull_requests]]
|
||||
uid = "4697"
|
||||
author_uid = "dependabot[bot]"
|
||||
closes_threads = []
|
||||
@@ -0,0 +1,5 @@
|
||||
internal = "Bump srvaroa/labeler from 1.12.0 to 1.13.0"
|
||||
[[pull_requests]]
|
||||
uid = "4698"
|
||||
author_uid = "dependabot[bot]"
|
||||
closes_threads = []
|
||||
@@ -0,0 +1,5 @@
|
||||
internal = "Bump astral-sh/setup-uv from 5.2.2 to 5.3.1"
|
||||
[[pull_requests]]
|
||||
uid = "4699"
|
||||
author_uid = "dependabot[bot]"
|
||||
closes_threads = []
|
||||
@@ -0,0 +1,5 @@
|
||||
internal = "Bump Bibo-Joshi/chango from 0.3.1 to 0.3.2"
|
||||
[[pull_requests]]
|
||||
uid = "4700"
|
||||
author_uid = "dependabot[bot]"
|
||||
closes_threads = []
|
||||
@@ -0,0 +1,5 @@
|
||||
internal = "Bump pypa/gh-action-pypi-publish from 1.12.3 to 1.12.4"
|
||||
[[pull_requests]]
|
||||
uid = "4701"
|
||||
author_uid = "dependabot[bot]"
|
||||
closes_threads = []
|
||||
@@ -0,0 +1,5 @@
|
||||
internal = "Bump pytest from 8.3.4 to 8.3.5"
|
||||
[[pull_requests]]
|
||||
uid = "4709"
|
||||
author_uid = "dependabot[bot]"
|
||||
closes_threads = []
|
||||
@@ -0,0 +1,5 @@
|
||||
internal = "Bump sphinx from 8.1.3 to 8.2.3"
|
||||
[[pull_requests]]
|
||||
uid = "4710"
|
||||
author_uid = "dependabot[bot]"
|
||||
closes_threads = []
|
||||
@@ -0,0 +1,5 @@
|
||||
internal = "Bump Bibo-Joshi/chango from 0.3.2 to 0.4.0"
|
||||
[[pull_requests]]
|
||||
uid = "4712"
|
||||
author_uid = "Bibo-Joshi"
|
||||
closes_threads = []
|
||||
@@ -0,0 +1,5 @@
|
||||
internal = "Bump Version to v22.0"
|
||||
[[pull_requests]]
|
||||
uid = "4719"
|
||||
author_uid = "Bibo-Joshi"
|
||||
closes_threads = []
|
||||
+2849
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,78 @@
|
||||
# noqa: INP001
|
||||
# pylint: disable=import-error
|
||||
"""Configuration for the chango changelog tool"""
|
||||
|
||||
from collections.abc import Collection
|
||||
from typing import Optional
|
||||
|
||||
from chango.concrete import DirectoryChanGo, DirectoryVersionScanner, HeaderVersionHistory
|
||||
from chango.concrete.sections import GitHubSectionChangeNote, Section, SectionVersionNote
|
||||
|
||||
version_scanner = DirectoryVersionScanner(base_directory=".", unreleased_directory="unreleased")
|
||||
|
||||
|
||||
class ChangoSectionChangeNote(
|
||||
GitHubSectionChangeNote.with_sections( # type: ignore[misc]
|
||||
[
|
||||
Section(uid="highlights", title="Highlights", sort_order=0),
|
||||
Section(uid="breaking", title="Breaking Changes", sort_order=1),
|
||||
Section(uid="security", title="Security Changes", sort_order=2),
|
||||
Section(uid="deprecations", title="Deprecations", sort_order=3),
|
||||
Section(uid="features", title="New Features", sort_order=4),
|
||||
Section(uid="bugfixes", title="Bug Fixes", sort_order=5),
|
||||
Section(uid="dependencies", title="Dependencies", sort_order=6),
|
||||
Section(uid="other", title="Other Changes", sort_order=7),
|
||||
Section(uid="documentation", title="Documentation", sort_order=8),
|
||||
Section(uid="internal", title="Internal Changes", sort_order=9),
|
||||
]
|
||||
)
|
||||
):
|
||||
"""Custom change note type for PTB. Mainly overrides get_sections to map labels to sections"""
|
||||
|
||||
OWNER = "python-telegram-bot"
|
||||
REPOSITORY = "python-telegram-bot"
|
||||
|
||||
@classmethod
|
||||
def get_sections(
|
||||
cls,
|
||||
labels: Collection[str],
|
||||
issue_types: Optional[Collection[str]],
|
||||
) -> set[str]:
|
||||
"""Override get_sections to have customized auto-detection of relevant sections based on
|
||||
the pull request and linked issues. Certainly not perfect in all cases, but should be a
|
||||
good start for most PRs.
|
||||
"""
|
||||
combined_labels = set(labels) | (set(issue_types or []))
|
||||
|
||||
mapping = {
|
||||
"🐛 bug": "bugfixes",
|
||||
"💡 feature": "features",
|
||||
"🧹 chore": "internal",
|
||||
"⚙️ bot-api": "features",
|
||||
"⚙️ documentation": "documentation",
|
||||
"⚙️ tests": "internal",
|
||||
"⚙️ ci-cd": "internal",
|
||||
"⚙️ security": "security",
|
||||
"⚙️ examples": "documentation",
|
||||
"⚙️ type-hinting": "other",
|
||||
"🛠 refactor": "internal",
|
||||
"🛠 breaking": "breaking",
|
||||
"⚙️ dependencies": "dependencies",
|
||||
"🔗 github-actions": "internal",
|
||||
"🛠 code-quality": "internal",
|
||||
}
|
||||
|
||||
# we want to return *all* from the mapping that are in the combined_labels
|
||||
# removing superfluous sections from the fragment is a tad easier than adding them
|
||||
found = {section for label, section in mapping.items() if label in combined_labels}
|
||||
|
||||
# if we have not found any sections, we default to "other"
|
||||
return found or {"other"}
|
||||
|
||||
|
||||
chango_instance = DirectoryChanGo(
|
||||
change_note_type=ChangoSectionChangeNote,
|
||||
version_note_type=SectionVersionNote,
|
||||
version_history_type=HeaderVersionHistory,
|
||||
scanner=version_scanner,
|
||||
)
|
||||
@@ -56,6 +56,8 @@ html:
|
||||
@echo
|
||||
@echo "Build finished. The HTML pages are in $(BUILDDIR)/html."
|
||||
|
||||
rebuild: clean html
|
||||
|
||||
dirhtml:
|
||||
$(SPHINXBUILD) -b dirhtml $(ALLSPHINXOPTS) $(BUILDDIR)/dirhtml
|
||||
@echo
|
||||
|
||||
@@ -0,0 +1,574 @@
|
||||
#
|
||||
# A library that provides a Python interface to the Telegram Bot API
|
||||
# Copyright (C) 2015-2025
|
||||
# Leandro Toledo de Souza <devs@python-telegram-bot.org>
|
||||
#
|
||||
# This program is free software: you can redistribute it and/or modify
|
||||
# it under the terms of the GNU Lesser Public License as published by
|
||||
# the Free Software Foundation, either version 3 of the License, or
|
||||
# (at your option) any later version.
|
||||
#
|
||||
# This program is distributed in the hope that it will be useful,
|
||||
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
# GNU Lesser Public License for more details.
|
||||
#
|
||||
# You should have received a copy of the GNU Lesser Public License
|
||||
# along with this program. If not, see [http://www.gnu.org/licenses/].
|
||||
import collections.abc
|
||||
import contextlib
|
||||
import inspect
|
||||
import re
|
||||
import typing
|
||||
from collections import defaultdict
|
||||
from collections.abc import Iterator
|
||||
from socket import socket
|
||||
from types import FunctionType
|
||||
from typing import Union
|
||||
|
||||
from apscheduler.job import Job as APSJob
|
||||
|
||||
import telegram
|
||||
import telegram._utils.defaultvalue
|
||||
import telegram._utils.types
|
||||
import telegram.ext
|
||||
import telegram.ext._utils.types
|
||||
from tests.auxil.slots import mro_slots
|
||||
|
||||
# Define the namespace for type resolution. This helps dealing with the internal imports that
|
||||
# we do in many places
|
||||
# The .copy() is important to avoid modifying the original namespace
|
||||
TG_NAMESPACE = vars(telegram).copy()
|
||||
TG_NAMESPACE.update(vars(telegram._utils.types))
|
||||
TG_NAMESPACE.update(vars(telegram._utils.defaultvalue))
|
||||
TG_NAMESPACE.update(vars(telegram.ext))
|
||||
TG_NAMESPACE.update(vars(telegram.ext._utils.types))
|
||||
TG_NAMESPACE.update(vars(telegram.ext._applicationbuilder))
|
||||
TG_NAMESPACE.update({"socket": socket, "APSJob": APSJob})
|
||||
|
||||
|
||||
class PublicMethod(typing.NamedTuple):
|
||||
name: str
|
||||
method: FunctionType
|
||||
|
||||
|
||||
def _is_inherited_method(cls: type, method_name: str) -> bool:
|
||||
"""Checks if a method is inherited from a parent class.
|
||||
Inheritance is not considered if the parent class is private.
|
||||
Recurses through all direcot or indirect parent classes.
|
||||
"""
|
||||
# The [1:] slice is used to exclude the class itself from the MRO.
|
||||
for base in cls.__mro__[1:]:
|
||||
if method_name in base.__dict__ and not base.__name__.startswith("_"):
|
||||
return True
|
||||
return False
|
||||
|
||||
|
||||
def _iter_own_public_methods(cls: type) -> Iterator[PublicMethod]:
|
||||
"""Iterates over methods of a class that are not protected/private,
|
||||
not camelCase and not inherited from the parent class.
|
||||
|
||||
Returns pairs of method names and methods.
|
||||
|
||||
This function is defined outside the class because it is used to create class constants.
|
||||
"""
|
||||
|
||||
# Use .isfunction() instead of .ismethod() because we want to include static methods.
|
||||
for m in inspect.getmembers(cls, predicate=inspect.isfunction):
|
||||
if (
|
||||
not m[0].startswith("_")
|
||||
and m[0].islower() # to avoid camelCase methods
|
||||
and not _is_inherited_method(cls, m[0])
|
||||
):
|
||||
yield PublicMethod(m[0], m[1])
|
||||
|
||||
|
||||
class AdmonitionInserter:
|
||||
"""Class for inserting admonitions into docs of Telegram classes."""
|
||||
|
||||
CLASS_ADMONITION_TYPES = ("use_in", "available_in", "returned_in")
|
||||
METHOD_ADMONITION_TYPES = ("shortcuts",)
|
||||
ALL_ADMONITION_TYPES = CLASS_ADMONITION_TYPES + METHOD_ADMONITION_TYPES
|
||||
|
||||
FORWARD_REF_PATTERN = re.compile(r"^ForwardRef\('(?P<class_name>\w+)'\)$")
|
||||
""" A pattern to find a class name in a ForwardRef typing annotation.
|
||||
Class name (in a named group) is surrounded by parentheses and single quotes.
|
||||
Note that since we're analyzing argument by argument, the pattern can be strict, with
|
||||
start and end markers.
|
||||
"""
|
||||
|
||||
METHOD_NAMES_FOR_BOT_APP_APPBUILDER: typing.ClassVar[dict[type, str]] = {
|
||||
cls: tuple(m.name for m in _iter_own_public_methods(cls))
|
||||
for cls in (telegram.Bot, telegram.ext.ApplicationBuilder, telegram.ext.Application)
|
||||
}
|
||||
"""A dictionary mapping Bot, Application & ApplicationBuilder classes to their relevant methods
|
||||
that will
|
||||
be mentioned in 'Returned in' and 'Use in' admonitions in other classes' docstrings.
|
||||
Methods must be public, not aliases, not inherited from TelegramObject.
|
||||
"""
|
||||
|
||||
def __init__(self):
|
||||
self.admonitions: dict[str, dict[Union[type, collections.abc.Callable], str]] = {
|
||||
# dynamically determine which method to use to create a sub-dictionary
|
||||
admonition_type: getattr(self, f"_create_{admonition_type}")()
|
||||
for admonition_type in self.ALL_ADMONITION_TYPES
|
||||
}
|
||||
"""Dictionary with admonitions. Contains sub-dictionaries, one per admonition type.
|
||||
Each sub-dictionary matches bot methods (for "Shortcuts") or telegram classes (for other
|
||||
admonition types) to texts of admonitions, e.g.:
|
||||
|
||||
```
|
||||
{
|
||||
"use_in": {
|
||||
<class 'telegram._chatinvitelink.ChatInviteLink'>:
|
||||
<"Use in" admonition for ChatInviteLink>,
|
||||
...
|
||||
},
|
||||
"available_in": {
|
||||
<class 'telegram._chatinvitelink.ChatInviteLink'>:
|
||||
<"Available in" admonition">,
|
||||
...
|
||||
},
|
||||
"returned_in": {...}
|
||||
}
|
||||
```
|
||||
"""
|
||||
|
||||
def insert_admonitions(
|
||||
self,
|
||||
obj: Union[type, collections.abc.Callable],
|
||||
docstring_lines: list[str],
|
||||
):
|
||||
"""Inserts admonitions into docstring lines for a given class or method.
|
||||
|
||||
**Modifies lines in place**.
|
||||
"""
|
||||
# A better way would be to copy the lines and return them, but that will not work with
|
||||
# docs.auxil.sphinx_hooks.autodoc_process_docstring()
|
||||
|
||||
for admonition_type in self.ALL_ADMONITION_TYPES:
|
||||
# If there is no admonition of the given type for the given class or method,
|
||||
# continue to the next admonition type, maybe the class/method is listed there.
|
||||
if obj not in self.admonitions[admonition_type]:
|
||||
continue
|
||||
|
||||
insert_idx = self._find_insert_pos_for_admonition(docstring_lines)
|
||||
admonition_lines = self.admonitions[admonition_type][obj].splitlines()
|
||||
|
||||
for idx in range(insert_idx, insert_idx + len(admonition_lines)):
|
||||
docstring_lines.insert(idx, admonition_lines[idx - insert_idx])
|
||||
|
||||
def _create_available_in(self) -> dict[type, str]:
|
||||
"""Creates a dictionary with 'Available in' admonitions for classes that are available
|
||||
in attributes of other classes.
|
||||
"""
|
||||
|
||||
# Generate a mapping of classes to ReST links to attributes in other classes that
|
||||
# correspond to instances of a given class
|
||||
# i.e. {telegram._files.sticker.Sticker: {":attr:`telegram.Message.sticker`", ...}}
|
||||
attrs_for_class = defaultdict(set)
|
||||
|
||||
classes_to_inspect = inspect.getmembers(telegram, inspect.isclass) + inspect.getmembers(
|
||||
telegram.ext, inspect.isclass
|
||||
)
|
||||
|
||||
for _class_name, inspected_class in classes_to_inspect:
|
||||
# We need to make "<class 'telegram._files.sticker.StickerSet'>" into
|
||||
# "telegram.StickerSet" because that's the way the classes are mentioned in
|
||||
# docstrings.
|
||||
name_of_inspected_class_in_docstr = self._generate_class_name_for_link(inspected_class)
|
||||
|
||||
# Writing to dictionary: matching the class found in the type hint
|
||||
# and its subclasses to the attribute of the class being inspected.
|
||||
# The class in the attribute typehint (or its subclass) is the key,
|
||||
# ReST link to attribute of the class currently being inspected is the value.
|
||||
|
||||
# best effort - args of __init__ means not all attributes are covered, but there is no
|
||||
# other way to get type hints of all attributes, other than doing ast parsing maybe.
|
||||
# (Docstring parsing was discontinued with the closing of #4414)
|
||||
type_hints = typing.get_type_hints(inspected_class.__init__, localns=TG_NAMESPACE)
|
||||
class_attrs = [slot for slot in mro_slots(inspected_class) if not slot.startswith("_")]
|
||||
for target_attr in class_attrs:
|
||||
try:
|
||||
self._resolve_arg_and_add_link(
|
||||
dict_of_methods_for_class=attrs_for_class,
|
||||
link=f":attr:`{name_of_inspected_class_in_docstr}.{target_attr}`",
|
||||
type_hints={target_attr: type_hints.get(target_attr)},
|
||||
resolve_nested_type_vars=False,
|
||||
)
|
||||
except NotImplementedError as e:
|
||||
raise NotImplementedError(
|
||||
"Error generating Sphinx 'Available in' admonition "
|
||||
f"(admonition_inserter.py). Class {inspected_class} present in "
|
||||
f"attribute {target_attr} of class {name_of_inspected_class_in_docstr}"
|
||||
f" could not be resolved. {e!s}"
|
||||
) from e
|
||||
|
||||
# Properties need to be parsed separately because they act like attributes but not
|
||||
# listed as attributes.
|
||||
properties = inspect.getmembers(inspected_class, lambda o: isinstance(o, property))
|
||||
for prop_name, _ in properties:
|
||||
# Make sure this property is really defined in the class being inspected.
|
||||
# A property can be inherited from a parent class, then a link to it will not work.
|
||||
if prop_name not in inspected_class.__dict__:
|
||||
continue
|
||||
|
||||
# fget is used to access the actual function under the property wrapper
|
||||
type_hints = typing.get_type_hints(
|
||||
getattr(inspected_class, prop_name).fget, localns=TG_NAMESPACE
|
||||
)
|
||||
|
||||
# Writing to dictionary: matching the class found in the docstring and its
|
||||
# subclasses to the property of the class being inspected.
|
||||
# The class in the property docstring (or its subclass) is the key,
|
||||
# ReST link to property of the class currently being inspected is the value.
|
||||
try:
|
||||
self._resolve_arg_and_add_link(
|
||||
dict_of_methods_for_class=attrs_for_class,
|
||||
link=f":attr:`{name_of_inspected_class_in_docstr}.{prop_name}`",
|
||||
type_hints={prop_name: type_hints.get("return")},
|
||||
resolve_nested_type_vars=False,
|
||||
)
|
||||
except NotImplementedError as e:
|
||||
raise NotImplementedError(
|
||||
"Error generating Sphinx 'Available in' admonition "
|
||||
f"(admonition_inserter.py). Class {inspected_class} present in "
|
||||
f"property {prop_name} of class {name_of_inspected_class_in_docstr}"
|
||||
f" could not be resolved. {e!s}"
|
||||
) from e
|
||||
|
||||
return self._generate_admonitions(attrs_for_class, admonition_type="available_in")
|
||||
|
||||
def _create_returned_in(self) -> dict[type, str]:
|
||||
"""Creates a dictionary with 'Returned in' admonitions for classes that are returned
|
||||
in Bot's and ApplicationBuilder's methods.
|
||||
"""
|
||||
# Generate a mapping of classes to ReST links to Bot methods which return it,
|
||||
# i.e. {<class 'telegram._message.Message'>: {:meth:`telegram.Bot.send_message`, ...}}
|
||||
methods_for_class = defaultdict(set)
|
||||
|
||||
for cls, method_names in self.METHOD_NAMES_FOR_BOT_APP_APPBUILDER.items():
|
||||
for method_name in method_names:
|
||||
method_link = self._generate_link_to_method(method_name, cls)
|
||||
arg = getattr(cls, method_name)
|
||||
ret_type_hint = typing.get_type_hints(arg, localns=TG_NAMESPACE)
|
||||
|
||||
try:
|
||||
self._resolve_arg_and_add_link(
|
||||
dict_of_methods_for_class=methods_for_class,
|
||||
link=method_link,
|
||||
type_hints={"return": ret_type_hint.get("return")},
|
||||
resolve_nested_type_vars=False,
|
||||
)
|
||||
except NotImplementedError as e:
|
||||
raise NotImplementedError(
|
||||
"Error generating Sphinx 'Returned in' admonition "
|
||||
f"(admonition_inserter.py). {cls}, method {method_name}. "
|
||||
f"Couldn't resolve type hint in return annotation {ret_type_hint}. {e!s}"
|
||||
) from e
|
||||
|
||||
return self._generate_admonitions(methods_for_class, admonition_type="returned_in")
|
||||
|
||||
def _create_shortcuts(self) -> dict[collections.abc.Callable, str]:
|
||||
"""Creates a dictionary with 'Shortcuts' admonitions for Bot methods that
|
||||
have shortcuts in other classes.
|
||||
"""
|
||||
|
||||
# pattern for looking for calls to Bot methods only
|
||||
bot_method_pattern = re.compile(
|
||||
r"""\s* # any number of whitespaces
|
||||
(?<=return\sawait\sself\.get_bot\(\)\.) # lookbehind
|
||||
\w+ # the method name we are looking for, letters/underscores
|
||||
(?=\() # lookahead: opening bracket before the args of the method start
|
||||
""",
|
||||
re.VERBOSE,
|
||||
)
|
||||
|
||||
# Generate a mapping of methods of classes to links to Bot methods which they are shortcuts
|
||||
# for, i.e. {<function Bot.send_voice at ...>: {:meth:`telegram.User.send_voice`, ...}
|
||||
shortcuts_for_bot_method = defaultdict(set)
|
||||
|
||||
# inspect methods of all telegram classes for return statements that indicate
|
||||
# that this given method is a shortcut for a Bot method
|
||||
for _class_name, cls in inspect.getmembers(telegram, predicate=inspect.isclass):
|
||||
if not cls.__module__.startswith("telegram"):
|
||||
# For some reason inspect.getmembers() also yields some classes that are
|
||||
# imported in the namespace but not part of the telegram module.
|
||||
continue
|
||||
|
||||
if cls is telegram.Bot:
|
||||
# no need to inspect Bot's own methods, as Bot can't have shortcuts in Bot
|
||||
continue
|
||||
|
||||
for method_name, method in _iter_own_public_methods(cls):
|
||||
# .getsourcelines() returns a tuple. Item [1] is an int
|
||||
for line in inspect.getsourcelines(method)[0]:
|
||||
if not (bot_method_match := bot_method_pattern.search(line)):
|
||||
continue
|
||||
|
||||
bot_method = getattr(telegram.Bot, bot_method_match.group())
|
||||
link_to_shortcut_method = self._generate_link_to_method(method_name, cls)
|
||||
shortcuts_for_bot_method[bot_method].add(link_to_shortcut_method)
|
||||
|
||||
return self._generate_admonitions(shortcuts_for_bot_method, admonition_type="shortcuts")
|
||||
|
||||
def _create_use_in(self) -> dict[type, str]:
|
||||
"""Creates a dictionary with 'Use in' admonitions for classes whose instances are
|
||||
accepted as arguments for Bot's and ApplicationBuilder's methods.
|
||||
"""
|
||||
|
||||
# Generate a mapping of classes to links to Bot methods which accept them as arguments,
|
||||
# i.e. {<class 'telegram._inline.inlinequeryresult.InlineQueryResult'>:
|
||||
# {:meth:`telegram.Bot.answer_inline_query`, ...}}
|
||||
methods_for_class = defaultdict(set)
|
||||
|
||||
for cls, method_names in self.METHOD_NAMES_FOR_BOT_APP_APPBUILDER.items():
|
||||
for method_name in method_names:
|
||||
method_link = self._generate_link_to_method(method_name, cls)
|
||||
|
||||
arg = getattr(cls, method_name)
|
||||
param_type_hints = typing.get_type_hints(arg, localns=TG_NAMESPACE)
|
||||
param_type_hints.pop("return", None)
|
||||
try:
|
||||
self._resolve_arg_and_add_link(
|
||||
dict_of_methods_for_class=methods_for_class,
|
||||
link=method_link,
|
||||
type_hints=param_type_hints,
|
||||
)
|
||||
except NotImplementedError as e:
|
||||
raise NotImplementedError(
|
||||
"Error generating Sphinx 'Use in' admonition "
|
||||
f"(admonition_inserter.py). {cls}, method {method_name}, parameter "
|
||||
) from e
|
||||
|
||||
return self._generate_admonitions(methods_for_class, admonition_type="use_in")
|
||||
|
||||
@staticmethod
|
||||
def _find_insert_pos_for_admonition(lines: list[str]) -> int:
|
||||
"""Finds the correct position to insert the class admonition and returns the index.
|
||||
|
||||
The admonition will be insert above "See also", "Examples:", version added/changed notes
|
||||
and args, whatever comes first.
|
||||
|
||||
If no key phrases are found, the admonition will be inserted at the very end.
|
||||
"""
|
||||
for idx, value in list(enumerate(lines)):
|
||||
if value.startswith(
|
||||
(
|
||||
# ".. seealso:",
|
||||
# The docstring contains heading "Examples:", but Sphinx will have it converted
|
||||
# to ".. admonition: Examples":
|
||||
".. admonition:: Examples",
|
||||
".. version",
|
||||
"Args:",
|
||||
# The space after ":param" is important because docstring can contain
|
||||
# ":paramref:" in its plain text in the beginning of a line (e.g. ExtBot):
|
||||
":param ",
|
||||
# some classes (like "Credentials") have no params, so insert before attrs:
|
||||
".. attribute::",
|
||||
)
|
||||
):
|
||||
return idx
|
||||
return len(lines) - 1
|
||||
|
||||
def _generate_admonitions(
|
||||
self,
|
||||
attrs_or_methods_for_class: dict[type, set[str]],
|
||||
admonition_type: str,
|
||||
) -> dict[type, str]:
|
||||
"""Generates admonitions of a given type.
|
||||
Takes a dictionary of classes matched to ReST links to methods or attributes, e.g.:
|
||||
|
||||
```
|
||||
{<class 'telegram._files.sticker.StickerSet'>:
|
||||
[":meth: `telegram.Bot.get_sticker_set`", ...]}.
|
||||
```
|
||||
|
||||
Returns a dictionary of classes matched to full admonitions, e.g.
|
||||
for `admonition_type` "returned_in" (note that title and CSS class are generated
|
||||
automatically):
|
||||
|
||||
```
|
||||
{<class 'telegram._files.sticker.StickerSet'>:
|
||||
".. admonition:: Returned in:
|
||||
:class: returned-in
|
||||
|
||||
:meth: `telegram.Bot.get_sticker_set`"}.
|
||||
```
|
||||
"""
|
||||
|
||||
if admonition_type not in self.ALL_ADMONITION_TYPES:
|
||||
raise TypeError(f"Admonition type {admonition_type} not supported.")
|
||||
|
||||
admonition_for_class = {}
|
||||
|
||||
for cls, attrs in attrs_or_methods_for_class.items():
|
||||
if cls is telegram.ext.ApplicationBuilder:
|
||||
# ApplicationBuilder is only used in and returned from its own methods,
|
||||
# so its page needs no admonitions.
|
||||
continue
|
||||
|
||||
sorted_attrs = sorted(attrs)
|
||||
|
||||
# e.g. for admonition type "use_in" the title will be "Use in" and CSS class "use-in".
|
||||
admonition = f"""
|
||||
|
||||
.. admonition:: {admonition_type.title().replace("_", " ")}
|
||||
:class: {admonition_type.replace("_", "-")}
|
||||
"""
|
||||
if len(sorted_attrs) > 1:
|
||||
for target_attr in sorted_attrs:
|
||||
admonition += "\n * " + target_attr
|
||||
else:
|
||||
admonition += f"\n {sorted_attrs[0]}"
|
||||
|
||||
admonition += "\n " # otherwise an unexpected unindent warning will be issued
|
||||
admonition_for_class[cls] = admonition
|
||||
|
||||
return admonition_for_class
|
||||
|
||||
@staticmethod
|
||||
def _generate_class_name_for_link(cls_: type) -> str:
|
||||
"""Generates class name that can be used in a ReST link."""
|
||||
|
||||
# Check for potential presence of ".ext.", we will need to keep it.
|
||||
ext = ".ext" if ".ext." in str(cls_) else ""
|
||||
return f"telegram{ext}.{cls_.__name__}"
|
||||
|
||||
def _generate_link_to_method(self, method_name: str, cls: type) -> str:
|
||||
"""Generates a ReST link to a method of a telegram class."""
|
||||
|
||||
return f":meth:`{self._generate_class_name_for_link(cls)}.{method_name}`"
|
||||
|
||||
@staticmethod
|
||||
def _iter_subclasses(cls_: type) -> Iterator:
|
||||
if not hasattr(cls_, "__subclasses__") or cls_ is telegram.TelegramObject:
|
||||
return iter([])
|
||||
return (
|
||||
# exclude private classes
|
||||
c
|
||||
for c in cls_.__subclasses__()
|
||||
if not str(c).split(".")[-1].startswith("_")
|
||||
)
|
||||
|
||||
def _resolve_arg_and_add_link(
|
||||
self,
|
||||
dict_of_methods_for_class: defaultdict,
|
||||
link: str,
|
||||
type_hints: dict[str, type],
|
||||
resolve_nested_type_vars: bool = True,
|
||||
) -> None:
|
||||
"""A helper method. Tries to resolve the arg into a valid class. In case of success,
|
||||
adds the link (to a method, attribute, or property) for that class' and its subclasses'
|
||||
sets of links in the dictionary of admonitions.
|
||||
|
||||
**Modifies dictionary in place.**
|
||||
"""
|
||||
type_hints.pop("self", None)
|
||||
|
||||
for cls in self._resolve_arg(type_hints, resolve_nested_type_vars):
|
||||
# When trying to resolve an argument from args or return annotation,
|
||||
# the method _resolve_arg returns None if nothing could be resolved.
|
||||
# Also, if class was resolved correctly, "telegram" will definitely be in its str().
|
||||
if cls is None or "telegram" not in str(cls):
|
||||
continue
|
||||
|
||||
dict_of_methods_for_class[cls].add(link)
|
||||
|
||||
for subclass in self._iter_subclasses(cls):
|
||||
dict_of_methods_for_class[subclass].add(link)
|
||||
|
||||
def _resolve_arg(
|
||||
self,
|
||||
type_hints: dict[str, type],
|
||||
resolve_nested_type_vars: bool,
|
||||
) -> list[type]:
|
||||
"""Analyzes an argument of a method and recursively yields classes that the argument
|
||||
or its sub-arguments (in cases like Union[...]) belong to, if they can be resolved to
|
||||
telegram or telegram.ext classes.
|
||||
|
||||
Args:
|
||||
type_hints: A dictionary of argument names and their types.
|
||||
resolve_nested_type_vars: If True, nested type variables (like Application[BT, …])
|
||||
will be resolved to their actual classes. If False, only the outermost type
|
||||
variable will be resolved. *Only* affects ptb classes, not built-in types.
|
||||
Useful for checking the return type of methods, where nested type variables
|
||||
are not really useful.
|
||||
|
||||
Raises `NotImplementedError`.
|
||||
"""
|
||||
|
||||
def _is_ptb_class(cls: type) -> bool:
|
||||
if not hasattr(cls, "__module__"):
|
||||
return False
|
||||
return cls.__module__.startswith("telegram")
|
||||
|
||||
# will be edited in place
|
||||
telegram_classes = set()
|
||||
|
||||
def recurse_type(type_, is_recursed_from_ptb_class: bool):
|
||||
next_is_recursed_from_ptb_class = is_recursed_from_ptb_class or _is_ptb_class(type_)
|
||||
|
||||
if hasattr(type_, "__origin__"): # For generic types like Union, List, etc.
|
||||
# Make sure it's not a telegram.ext generic type (e.g. ContextTypes[...])
|
||||
org = typing.get_origin(type_)
|
||||
if "telegram.ext" in str(org):
|
||||
telegram_classes.add(org)
|
||||
|
||||
args = typing.get_args(type_)
|
||||
for arg in args:
|
||||
recurse_type(arg, next_is_recursed_from_ptb_class)
|
||||
elif isinstance(type_, typing.TypeVar) and (
|
||||
resolve_nested_type_vars or not is_recursed_from_ptb_class
|
||||
):
|
||||
# gets access to the "bound=..." parameter
|
||||
recurse_type(type_.__bound__, next_is_recursed_from_ptb_class)
|
||||
elif inspect.isclass(type_) and "telegram" in inspect.getmodule(type_).__name__:
|
||||
telegram_classes.add(type_)
|
||||
elif isinstance(type_, typing.ForwardRef):
|
||||
# Resolving ForwardRef is not easy. https://peps.python.org/pep-0749/ will
|
||||
# hopefully make it better by introducing typing.resolve_forward_ref() in py3.14
|
||||
# but that's not there yet
|
||||
# So for now we fall back to a best effort approach of guessing if the class is
|
||||
# available in tg or tg.ext
|
||||
with contextlib.suppress(AttributeError):
|
||||
telegram_classes.add(self._resolve_class(type_.__forward_arg__))
|
||||
|
||||
for type_hint in type_hints.values():
|
||||
if type_hint is not None:
|
||||
recurse_type(type_hint, False)
|
||||
|
||||
return list(telegram_classes)
|
||||
|
||||
@staticmethod
|
||||
def _resolve_class(name: str) -> Union[type, None]:
|
||||
"""The keys in the admonitions dictionary are not strings like "telegram.StickerSet"
|
||||
but classes like <class 'telegram._files.sticker.StickerSet'>.
|
||||
|
||||
This method attempts to resolve a PTB class from a name that does or does not
|
||||
contain the word 'telegram', e.g.
|
||||
<class 'telegram._files.sticker.StickerSet'> from "telegram.StickerSet" or "StickerSet".
|
||||
|
||||
Returns a class on success, :obj:`None` if nothing could be resolved.
|
||||
"""
|
||||
|
||||
for option in (
|
||||
name,
|
||||
f"telegram.{name}",
|
||||
f"telegram.ext.{name}",
|
||||
f"telegram.ext.filters.{name}",
|
||||
):
|
||||
# NameError will be raised if trying to eval just name and it doesn't work, e.g.
|
||||
# "Name 'ApplicationBuilder' is not defined".
|
||||
# AttributeError will be raised if trying to e.g. eval f"telegram.{name}" when the
|
||||
# class denoted by `name` actually belongs to `telegram.ext`:
|
||||
# "module 'telegram' has no attribute 'ApplicationBuilder'".
|
||||
# If neither option works, this is not a PTB class.
|
||||
with contextlib.suppress(NameError, AttributeError):
|
||||
return eval(option)
|
||||
return None
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
# just try instantiating for debugging purposes
|
||||
AdmonitionInserter()
|
||||
@@ -0,0 +1,108 @@
|
||||
#
|
||||
# A library that provides a Python interface to the Telegram Bot API
|
||||
# Copyright (C) 2015-2025
|
||||
# Leandro Toledo de Souza <devs@python-telegram-bot.org>
|
||||
#
|
||||
# This program is free software: you can redistribute it and/or modify
|
||||
# it under the terms of the GNU Lesser Public License as published by
|
||||
# the Free Software Foundation, either version 3 of the License, or
|
||||
# (at your option) any later version.
|
||||
#
|
||||
# This program is distributed in the hope that it will be useful,
|
||||
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
# GNU Lesser Public License for more details.
|
||||
#
|
||||
# You should have received a copy of the GNU Lesser Public License
|
||||
# along with this program. If not, see [http://www.gnu.org/licenses/].
|
||||
import inspect
|
||||
|
||||
keyword_args = [
|
||||
"Keyword Arguments:",
|
||||
(
|
||||
" read_timeout (:obj:`float` | :obj:`None`, optional): Value to pass to "
|
||||
" :paramref:`telegram.request.BaseRequest.post.read_timeout`. Defaults to "
|
||||
" :attr:`~telegram.request.BaseRequest.DEFAULT_NONE`. "
|
||||
),
|
||||
(
|
||||
" write_timeout (:obj:`float` | :obj:`None`, optional): Value to pass to "
|
||||
" :paramref:`telegram.request.BaseRequest.post.write_timeout`. Defaults to "
|
||||
" :attr:`~telegram.request.BaseRequest.DEFAULT_NONE`."
|
||||
),
|
||||
(
|
||||
" connect_timeout (:obj:`float` | :obj:`None`, optional): Value to pass to "
|
||||
" :paramref:`telegram.request.BaseRequest.post.connect_timeout`. Defaults to "
|
||||
" :attr:`~telegram.request.BaseRequest.DEFAULT_NONE`."
|
||||
),
|
||||
(
|
||||
" pool_timeout (:obj:`float` | :obj:`None`, optional): Value to pass to "
|
||||
" :paramref:`telegram.request.BaseRequest.post.pool_timeout`. Defaults to "
|
||||
" :attr:`~telegram.request.BaseRequest.DEFAULT_NONE`."
|
||||
),
|
||||
(
|
||||
" api_kwargs (:obj:`dict`, optional): Arbitrary keyword arguments"
|
||||
" to be passed to the Telegram API. See :meth:`~telegram.Bot.do_api_request` for"
|
||||
" limitations."
|
||||
),
|
||||
"",
|
||||
]
|
||||
|
||||
media_write_timeout_change_methods = [
|
||||
"add_sticker_to_set",
|
||||
"create_new_sticker_set",
|
||||
"send_animation",
|
||||
"send_audio",
|
||||
"send_document",
|
||||
"send_media_group",
|
||||
"send_photo",
|
||||
"send_sticker",
|
||||
"send_video",
|
||||
"send_video_note",
|
||||
"send_voice",
|
||||
"set_chat_photo",
|
||||
"upload_sticker_file",
|
||||
]
|
||||
media_write_timeout_change = [
|
||||
" write_timeout (:obj:`float` | :obj:`None`, optional): Value to pass to "
|
||||
" :paramref:`telegram.request.BaseRequest.post.write_timeout`. By default, ``20`` "
|
||||
" seconds are used as write timeout."
|
||||
"",
|
||||
"",
|
||||
" .. versionchanged:: 22.0",
|
||||
" The default value changed to "
|
||||
" :attr:`~telegram.request.BaseRequest.DEFAULT_NONE`.",
|
||||
"",
|
||||
"",
|
||||
]
|
||||
get_updates_read_timeout_addition = [
|
||||
" :paramref:`timeout` will be added to this value.",
|
||||
"",
|
||||
"",
|
||||
" .. versionchanged:: 20.7",
|
||||
" Defaults to :attr:`~telegram.request.BaseRequest.DEFAULT_NONE` instead of ",
|
||||
" ``2``.",
|
||||
]
|
||||
|
||||
|
||||
def find_insert_pos_for_kwargs(lines: list[str]) -> int:
|
||||
"""Finds the correct position to insert the keyword arguments and returns the index."""
|
||||
for idx, value in reversed(list(enumerate(lines))): # reversed since :returns: is at the end
|
||||
if value.startswith("Returns"):
|
||||
return idx
|
||||
return False
|
||||
|
||||
|
||||
def check_timeout_and_api_kwargs_presence(obj: object) -> int:
|
||||
"""Checks if the method has timeout and api_kwargs keyword only parameters."""
|
||||
sig = inspect.signature(obj)
|
||||
params_to_check = (
|
||||
"read_timeout",
|
||||
"write_timeout",
|
||||
"connect_timeout",
|
||||
"pool_timeout",
|
||||
"api_kwargs",
|
||||
)
|
||||
return all(
|
||||
param in sig.parameters and sig.parameters[param].kind == inspect.Parameter.KEYWORD_ONLY
|
||||
for param in params_to_check
|
||||
)
|
||||
@@ -0,0 +1,78 @@
|
||||
#
|
||||
# A library that provides a Python interface to the Telegram Bot API
|
||||
# Copyright (C) 2015-2025
|
||||
# Leandro Toledo de Souza <devs@python-telegram-bot.org>
|
||||
#
|
||||
# This program is free software: you can redistribute it and/or modify
|
||||
# it under the terms of the GNU Lesser Public License as published by
|
||||
# the Free Software Foundation, either version 3 of the License, or
|
||||
# (at your option) any later version.
|
||||
#
|
||||
# This program is distributed in the hope that it will be useful,
|
||||
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
# GNU Lesser Public License for more details.
|
||||
#
|
||||
# You should have received a copy of the GNU Lesser Public License
|
||||
# along with this program. If not, see [http://www.gnu.org/licenses/].
|
||||
"""Functionality in this file is used for getting the [source] links on the classes, methods etc
|
||||
to link to the correct files & lines on github. Can be simplified once
|
||||
https://github.com/sphinx-doc/sphinx/issues/1556 is closed
|
||||
"""
|
||||
import subprocess
|
||||
from pathlib import Path
|
||||
|
||||
from sphinx.util import logging
|
||||
|
||||
# get the sphinx(!) logger
|
||||
# Makes sure logs render in red and also plays nicely with e.g. the `nitpicky` option.
|
||||
sphinx_logger = logging.getLogger(__name__)
|
||||
|
||||
|
||||
# must be a module-level variable so that it can be written to by the `autodoc-process-docstring`
|
||||
# event handler in `sphinx_hooks.py`
|
||||
LINE_NUMBERS: dict[str, tuple[Path, int, int]] = {}
|
||||
|
||||
|
||||
def _git_branch() -> str:
|
||||
"""Get's the current git sha if available or fall back to `master`"""
|
||||
try:
|
||||
output = subprocess.check_output(
|
||||
["git", "describe", "--tags", "--always"], stderr=subprocess.STDOUT
|
||||
)
|
||||
return output.decode().strip()
|
||||
except Exception as exc:
|
||||
sphinx_logger.exception(
|
||||
"Failed to get a description of the current commit. Falling back to `master`.",
|
||||
exc_info=exc,
|
||||
)
|
||||
return "master"
|
||||
|
||||
|
||||
git_branch = _git_branch()
|
||||
base_url = "https://github.com/python-telegram-bot/python-telegram-bot/blob/"
|
||||
|
||||
|
||||
def linkcode_resolve(_, info) -> str:
|
||||
"""See www.sphinx-doc.org/en/master/usage/extensions/linkcode.html"""
|
||||
combined = ".".join((info["module"], info["fullname"]))
|
||||
# special casing for ExtBot which is due to the special structure of extbot.rst
|
||||
combined = combined.replace("ExtBot.ExtBot", "ExtBot")
|
||||
|
||||
line_info = LINE_NUMBERS.get(combined)
|
||||
|
||||
if not line_info:
|
||||
# Try the __init__
|
||||
line_info = LINE_NUMBERS.get(f"{combined.rsplit('.', 1)[0]}.__init__")
|
||||
if not line_info:
|
||||
# Try the class
|
||||
line_info = LINE_NUMBERS.get(f"{combined.rsplit('.', 1)[0]}")
|
||||
if not line_info:
|
||||
# Try the module
|
||||
line_info = LINE_NUMBERS.get(info["module"])
|
||||
|
||||
if not line_info:
|
||||
return None
|
||||
|
||||
file, start_line, end_line = line_info
|
||||
return f"{base_url}{git_branch}/{file}#L{start_line}-L{end_line}"
|
||||
@@ -0,0 +1,220 @@
|
||||
#
|
||||
# A library that provides a Python interface to the Telegram Bot API
|
||||
# Copyright (C) 2015-2025
|
||||
# Leandro Toledo de Souza <devs@python-telegram-bot.org>
|
||||
#
|
||||
# This program is free software: you can redistribute it and/or modify
|
||||
# it under the terms of the GNU Lesser Public License as published by
|
||||
# the Free Software Foundation, either version 3 of the License, or
|
||||
# (at your option) any later version.
|
||||
#
|
||||
# This program is distributed in the hope that it will be useful,
|
||||
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
# GNU Lesser Public License for more details.
|
||||
#
|
||||
# You should have received a copy of the GNU Lesser Public License
|
||||
# along with this program. If not, see [http://www.gnu.org/licenses/].
|
||||
import collections.abc
|
||||
import contextlib
|
||||
import inspect
|
||||
import re
|
||||
import typing
|
||||
from pathlib import Path
|
||||
|
||||
from sphinx.application import Sphinx
|
||||
|
||||
import telegram
|
||||
import telegram.ext
|
||||
from docs.auxil.admonition_inserter import AdmonitionInserter
|
||||
from docs.auxil.kwargs_insertion import (
|
||||
check_timeout_and_api_kwargs_presence,
|
||||
find_insert_pos_for_kwargs,
|
||||
get_updates_read_timeout_addition,
|
||||
keyword_args,
|
||||
media_write_timeout_change,
|
||||
media_write_timeout_change_methods,
|
||||
)
|
||||
from docs.auxil.link_code import LINE_NUMBERS
|
||||
|
||||
ADMONITION_INSERTER = AdmonitionInserter()
|
||||
|
||||
# Some base classes are implementation detail
|
||||
# We want to instead show *their* base class
|
||||
PRIVATE_BASE_CLASSES = {
|
||||
"_ChatUserBaseFilter": "MessageFilter",
|
||||
"_Dice": "MessageFilter",
|
||||
"_BaseThumbedMedium": "TelegramObject",
|
||||
"_BaseMedium": "TelegramObject",
|
||||
"_CredentialsBase": "TelegramObject",
|
||||
"_ChatBase": "TelegramObject",
|
||||
}
|
||||
|
||||
|
||||
FILE_ROOT = Path(inspect.getsourcefile(telegram)).parent.parent.resolve()
|
||||
|
||||
|
||||
def autodoc_skip_member(app, what, name, obj, skip, options):
|
||||
"""We use this to not document certain members like filter() or check_update() for filters.
|
||||
See https://www.sphinx-doc.org/en/master/usage/extensions/autodoc.html#skipping-members"""
|
||||
|
||||
included = {"MessageFilter", "UpdateFilter"} # filter() and check_update() only for these.
|
||||
included_in_obj = any(inc in repr(obj) for inc in included)
|
||||
|
||||
if included_in_obj: # it's difficult to see if check_update is from an inherited-member or not
|
||||
for frame in inspect.stack(): # From https://github.com/sphinx-doc/sphinx/issues/9533
|
||||
if frame.function == "filter_members":
|
||||
docobj = frame.frame.f_locals["self"].object
|
||||
if not any(inc in str(docobj) for inc in included) and name == "check_update":
|
||||
return True
|
||||
break
|
||||
|
||||
if name == "filter" and obj.__module__ == "telegram.ext.filters" and not included_in_obj:
|
||||
return True # return True to exclude from docs.
|
||||
return None
|
||||
|
||||
|
||||
def autodoc_process_docstring(
|
||||
app: Sphinx, what, name: str, obj: object, options, lines: list[str]
|
||||
):
|
||||
"""We do the following things:
|
||||
1) Use this method to automatically insert the Keyword Args and "Shortcuts" admonitions
|
||||
for the Bot methods.
|
||||
|
||||
2) Use this method to automatically insert "Returned in" admonition into classes
|
||||
that are returned from the Bot methods
|
||||
|
||||
3) Use this method to automatically insert "Available in" admonition into classes
|
||||
whose instances are available as attributes of other classes
|
||||
|
||||
4) Use this method to automatically insert "Use in" admonition into classes
|
||||
whose instances can be used as arguments of the Bot methods
|
||||
|
||||
5) Misuse this autodoc hook to get the file names & line numbers because we have access
|
||||
to the actual object here.
|
||||
"""
|
||||
|
||||
# 1) Insert the Keyword Args and "Shortcuts" admonitions for the Bot methods
|
||||
method_name = name.split(".")[-1]
|
||||
if (
|
||||
name.startswith("telegram.Bot.")
|
||||
and what == "method"
|
||||
and method_name.islower()
|
||||
and check_timeout_and_api_kwargs_presence(obj)
|
||||
):
|
||||
insert_index = find_insert_pos_for_kwargs(lines)
|
||||
if not insert_index:
|
||||
raise ValueError(
|
||||
f"Couldn't find the correct position to insert the keyword args for {obj}."
|
||||
)
|
||||
|
||||
get_updates: bool = method_name == "get_updates"
|
||||
# The below can be done in 1 line with itertools.chain, but this must be modified in-place
|
||||
insert_idx = insert_index
|
||||
for i in range(insert_index, insert_index + len(keyword_args)):
|
||||
to_insert = keyword_args[i - insert_index]
|
||||
|
||||
if (
|
||||
"post.write_timeout`. Defaults to" in to_insert
|
||||
and method_name in media_write_timeout_change_methods
|
||||
):
|
||||
effective_insert: list[str] = media_write_timeout_change
|
||||
elif get_updates and to_insert.lstrip().startswith("read_timeout"):
|
||||
effective_insert = [to_insert, *get_updates_read_timeout_addition]
|
||||
else:
|
||||
effective_insert = [to_insert]
|
||||
|
||||
lines[insert_idx:insert_idx] = effective_insert
|
||||
insert_idx += len(effective_insert)
|
||||
|
||||
ADMONITION_INSERTER.insert_admonitions(
|
||||
obj=typing.cast(collections.abc.Callable, obj),
|
||||
docstring_lines=lines,
|
||||
)
|
||||
|
||||
# 2-4) Insert "Returned in", "Available in", "Use in" admonitions into classes
|
||||
# (where applicable)
|
||||
if what == "class":
|
||||
ADMONITION_INSERTER.insert_admonitions(
|
||||
obj=typing.cast(type, obj), # since "what" == class, we know it's not just object
|
||||
docstring_lines=lines,
|
||||
)
|
||||
|
||||
# 5) Get the file names & line numbers
|
||||
# We can't properly handle ordinary attributes.
|
||||
# In linkcode_resolve we'll resolve to the `__init__` or module instead
|
||||
if what == "attribute":
|
||||
return
|
||||
|
||||
# Special casing for properties
|
||||
if hasattr(obj, "fget"):
|
||||
obj = obj.fget
|
||||
|
||||
# Special casing for filters
|
||||
if isinstance(obj, telegram.ext.filters.BaseFilter):
|
||||
obj = obj.__class__
|
||||
|
||||
with contextlib.suppress(Exception):
|
||||
source_lines, start_line = inspect.getsourcelines(obj)
|
||||
end_line = start_line + len(source_lines)
|
||||
file = Path(inspect.getsourcefile(obj)).relative_to(FILE_ROOT)
|
||||
LINE_NUMBERS[name] = (file, start_line, end_line)
|
||||
|
||||
# Since we don't document the `__init__`, we call this manually to have it available for
|
||||
# attributes -- see the note above
|
||||
if what == "class":
|
||||
autodoc_process_docstring(app, "method", f"{name}.__init__", obj.__init__, options, lines)
|
||||
|
||||
|
||||
def autodoc_process_bases(app, name, obj, option, bases: list) -> None:
|
||||
"""Here we fine tune how the base class's classes are displayed."""
|
||||
for idx, raw_base in enumerate(bases):
|
||||
# let's use a string representation of the object
|
||||
base = str(raw_base)
|
||||
|
||||
# Special case for abstract context managers which are wrongly resoled for some reason
|
||||
if base.startswith("typing.AbstractAsyncContextManager"):
|
||||
bases[idx] = ":class:`contextlib.AbstractAsyncContextManager`"
|
||||
continue
|
||||
|
||||
# Special case because base classes are in std lib:
|
||||
if "StringEnum" in base == "<enum 'StringEnum'>":
|
||||
bases[idx] = ":class:`enum.Enum`"
|
||||
bases.insert(0, ":class:`str`")
|
||||
continue
|
||||
|
||||
if "IntEnum" in base:
|
||||
bases[idx] = ":class:`enum.IntEnum`"
|
||||
continue
|
||||
|
||||
if "FloatEnum" in base:
|
||||
bases[idx] = ":class:`enum.Enum`"
|
||||
bases.insert(0, ":class:`float`")
|
||||
continue
|
||||
|
||||
# Drop generics (at least for now)
|
||||
if base.endswith("]"):
|
||||
base = base.split("[", maxsplit=1)[0]
|
||||
bases[idx] = f":class:`{base}`"
|
||||
|
||||
# Now convert `telegram._message.Message` to `telegram.Message` etc
|
||||
if (
|
||||
not (match := re.search(pattern=r"(telegram(\.ext|))\.[_\w\.]+", string=base))
|
||||
or "_utils" in base
|
||||
):
|
||||
continue
|
||||
|
||||
parts = match.group(0).split(".")
|
||||
|
||||
# Remove private paths
|
||||
for index, part in enumerate(parts):
|
||||
if part.startswith("_"):
|
||||
parts = parts[:index] + parts[-1:]
|
||||
break
|
||||
|
||||
# Replace private base classes with their respective parent
|
||||
parts = [PRIVATE_BASE_CLASSES.get(part, part) for part in parts]
|
||||
|
||||
base = ".".join(parts)
|
||||
|
||||
bases[idx] = f":class:`{base}`"
|
||||
@@ -0,0 +1,101 @@
|
||||
#
|
||||
# A library that provides a Python interface to the Telegram Bot API
|
||||
# Copyright (C) 2015-2025
|
||||
# Leandro Toledo de Souza <devs@python-telegram-bot.org>
|
||||
#
|
||||
# This program is free software: you can redistribute it and/or modify
|
||||
# it under the terms of the GNU Lesser Public License as published by
|
||||
# the Free Software Foundation, either version 3 of the License, or
|
||||
# (at your option) any later version.
|
||||
#
|
||||
# This program is distributed in the hope that it will be useful,
|
||||
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
# GNU Lesser Public License for more details.
|
||||
#
|
||||
# You should have received a copy of the GNU Lesser Public License
|
||||
# along with this program. If not, see [http://www.gnu.org/licenses/].
|
||||
import datetime as dtm
|
||||
from enum import Enum
|
||||
|
||||
from docutils.nodes import Element
|
||||
from sphinx.domains.python import PyXRefRole
|
||||
from sphinx.environment import BuildEnvironment
|
||||
from sphinx.util import logging
|
||||
|
||||
import telegram
|
||||
|
||||
# get the sphinx(!) logger
|
||||
# Makes sure logs render in red and also plays nicely with e.g. the `nitpicky` option.
|
||||
sphinx_logger = logging.getLogger(__name__)
|
||||
|
||||
CONSTANTS_ROLE = "tg-const"
|
||||
|
||||
|
||||
class TGConstXRefRole(PyXRefRole):
|
||||
"""This is a bit of Sphinx magic. We add a new role type called tg-const that allows us to
|
||||
reference values from the `telegram.constants.module` while using the actual value as title
|
||||
of the link.
|
||||
|
||||
Example:
|
||||
|
||||
:tg-const:`telegram.constants.MessageLimit.MAX_TEXT_LENGTH` renders as `4096` but links to
|
||||
the constant.
|
||||
"""
|
||||
|
||||
def process_link(
|
||||
self,
|
||||
env: BuildEnvironment,
|
||||
refnode: Element,
|
||||
has_explicit_title: bool,
|
||||
title: str,
|
||||
target: str,
|
||||
) -> tuple[str, str]:
|
||||
title, target = super().process_link(env, refnode, has_explicit_title, title, target)
|
||||
try:
|
||||
# We use `eval` to get the value of the expression. Maybe there are better ways to
|
||||
# do this via importlib or so, but it does the job for now
|
||||
value = eval(target)
|
||||
# Maybe we need a better check if the target is actually from tg.constants
|
||||
# for now checking if it's an Enum suffices since those are used nowhere else in PTB
|
||||
if isinstance(value, Enum):
|
||||
# Special casing for file size limits
|
||||
if isinstance(value, telegram.constants.FileSizeLimit):
|
||||
return f"{int(value.value / 1e6)} MB", target
|
||||
return repr(value.value), target
|
||||
# Just for (Bot API) versions number auto add in constants:
|
||||
if isinstance(value, str) and target in (
|
||||
"telegram.constants.BOT_API_VERSION",
|
||||
"telegram.__version__",
|
||||
):
|
||||
return value, target
|
||||
if isinstance(value, tuple) and target in (
|
||||
"telegram.constants.BOT_API_VERSION_INFO",
|
||||
"telegram.__version_info__",
|
||||
):
|
||||
return str(value), target
|
||||
if (
|
||||
isinstance(value, dtm.datetime)
|
||||
and value == telegram.constants.ZERO_DATE
|
||||
and target in ("telegram.constants.ZERO_DATE",)
|
||||
):
|
||||
return repr(value), target
|
||||
sphinx_logger.warning(
|
||||
"%s:%d: WARNING: Did not convert reference %s. :%s: is not supposed"
|
||||
" to be used with this type of target.",
|
||||
refnode.source,
|
||||
refnode.line,
|
||||
refnode.rawsource,
|
||||
CONSTANTS_ROLE,
|
||||
)
|
||||
except Exception as exc:
|
||||
sphinx_logger.exception(
|
||||
"%s:%d: WARNING: Did not convert reference %s due to an exception.",
|
||||
refnode.source,
|
||||
refnode.line,
|
||||
refnode.rawsource,
|
||||
exc_info=exc,
|
||||
)
|
||||
return title, target
|
||||
else:
|
||||
return title, target
|
||||
@@ -1,5 +1,10 @@
|
||||
sphinx==5.0.2
|
||||
sphinx-pypi-upload
|
||||
furo==2022.6.21
|
||||
sphinx-paramlinks==0.5.4
|
||||
sphinxcontrib-mermaid==0.7.1
|
||||
chango~=0.4.0
|
||||
sphinx==8.2.3
|
||||
furo==2024.8.6
|
||||
furo-sphinx-search @ git+https://github.com/harshil21/furo-sphinx-search@v0.2.0.1
|
||||
sphinx-paramlinks==0.6.0
|
||||
sphinxcontrib-mermaid==1.0.0
|
||||
sphinx-copybutton==0.5.2
|
||||
sphinx-inline-tabs==2023.4.21
|
||||
# Temporary. See #4387
|
||||
sphinx-build-compatibility @ git+https://github.com/readthedocs/sphinx-build-compatibility.git@58aabc5f207c6c2421f23d3578adc0b14af57047
|
||||
|
||||
@@ -0,0 +1,65 @@
|
||||
:root {
|
||||
--icon--shortcuts: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='16' height='16' fill='currentColor' class='bi bi-signpost' viewBox='0 0 16 16'%3E%3Cpath d='M7 1.414V4H2a1 1 0 0 0-1 1v4a1 1 0 0 0 1 1h5v6h2v-6h3.532a1 1 0 0 0 .768-.36l1.933-2.32a.5.5 0 0 0 0-.64L13.3 4.36a1 1 0 0 0-.768-.36H9V1.414a1 1 0 0 0-2 0zM12.532 5l1.666 2-1.666 2H2V5h10.532z'/%3E%3C/svg%3E");
|
||||
--icon--returned-in: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='16' height='16' fill='currentColor' class='bi bi-arrow-return-right' viewBox='0 0 16 16'%3E%3Cpath fill-rule='evenodd' d='M1.5 1.5A.5.5 0 0 0 1 2v4.8a2.5 2.5 0 0 0 2.5 2.5h9.793l-3.347 3.346a.5.5 0 0 0 .708.708l4.2-4.2a.5.5 0 0 0 0-.708l-4-4a.5.5 0 0 0-.708.708L13.293 8.3H3.5A1.5 1.5 0 0 1 2 6.8V2a.5.5 0 0 0-.5-.5z'/%3E%3C/svg%3E");
|
||||
--icon--available-in: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='16' height='16' fill='currentColor' class='bi bi-geo-fill' viewBox='0 0 16 16'%3E%3Cpath fill-rule='evenodd' d='M4 4a4 4 0 1 1 4.5 3.969V13.5a.5.5 0 0 1-1 0V7.97A4 4 0 0 1 4 3.999zm2.493 8.574a.5.5 0 0 1-.411.575c-.712.118-1.28.295-1.655.493a1.319 1.319 0 0 0-.37.265.301.301 0 0 0-.057.09V14l.002.008a.147.147 0 0 0 .016.033.617.617 0 0 0 .145.15c.165.13.435.27.813.395.751.25 1.82.414 3.024.414s2.273-.163 3.024-.414c.378-.126.648-.265.813-.395a.619.619 0 0 0 .146-.15.148.148 0 0 0 .015-.033L12 14v-.004a.301.301 0 0 0-.057-.09 1.318 1.318 0 0 0-.37-.264c-.376-.198-.943-.375-1.655-.493a.5.5 0 1 1 .164-.986c.77.127 1.452.328 1.957.594C12.5 13 13 13.4 13 14c0 .426-.26.752-.544.977-.29.228-.68.413-1.116.558-.878.293-2.059.465-3.34.465-1.281 0-2.462-.172-3.34-.465-.436-.145-.826-.33-1.116-.558C3.26 14.752 3 14.426 3 14c0-.599.5-1 .961-1.243.505-.266 1.187-.467 1.957-.594a.5.5 0 0 1 .575.411z'/%3E%3C/svg%3E");
|
||||
--icon--use-in:url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='16' height='16' fill='currentColor' class='bi bi-funnel' viewBox='0 0 16 16'%3E%3Cpath d='M1.5 1.5A.5.5 0 0 1 2 1h12a.5.5 0 0 1 .5.5v2a.5.5 0 0 1-.128.334L10 8.692V13.5a.5.5 0 0 1-.342.474l-3 1A.5.5 0 0 1 6 14.5V8.692L1.628 3.834A.5.5 0 0 1 1.5 3.5v-2zm1 .5v1.308l4.372 4.858A.5.5 0 0 1 7 8.5v5.306l2-.666V8.5a.5.5 0 0 1 .128-.334L13.5 3.308V2h-11z'/%3E%3C/svg%3E");
|
||||
}
|
||||
.admonition.shortcuts {
|
||||
border-color: rgb(43, 155, 70);
|
||||
}
|
||||
.admonition.shortcuts > .admonition-title {
|
||||
background-color: rgba(43, 155, 70, 0.1);
|
||||
border-color: rgb(43, 155, 70);
|
||||
}
|
||||
.admonition.shortcuts > .admonition-title::before {
|
||||
background-color: rgb(43, 155, 70);
|
||||
-webkit-mask-image: var(--icon--shortcuts);
|
||||
mask-image: var(--icon--shortcuts);
|
||||
}
|
||||
|
||||
.admonition.returned-in {
|
||||
border-color: rgb(230, 109, 15);
|
||||
}
|
||||
.admonition.returned-in > .admonition-title {
|
||||
background-color: rgba(177, 108, 51, 0.1);
|
||||
border-color: rgb(230, 109, 15);
|
||||
}
|
||||
.admonition.returned-in > .admonition-title::before {
|
||||
background-color: rgb(230, 109, 15);
|
||||
-webkit-mask-image: var(--icon--returned-in);
|
||||
mask-image: var(--icon--returned-in);
|
||||
}
|
||||
|
||||
.admonition.available-in {
|
||||
border-color: rgb(183, 4, 215);
|
||||
}
|
||||
.admonition.available-in > .admonition-title {
|
||||
background-color: rgba(165, 99, 177, 0.1);
|
||||
border-color: rgb(183, 4, 215);
|
||||
}
|
||||
.admonition.available-in > .admonition-title::before {
|
||||
background-color: rgb(183, 4, 215);
|
||||
-webkit-mask-image: var(--icon--available-in);
|
||||
mask-image: var(--icon--available-in);
|
||||
}
|
||||
|
||||
.admonition.use-in {
|
||||
border-color: rgb(203, 147, 1);
|
||||
}
|
||||
.admonition.use-in > .admonition-title {
|
||||
background-color: rgba(176, 144, 60, 0.1);
|
||||
border-color: rgb(203, 147, 1);
|
||||
}
|
||||
.admonition.use-in > .admonition-title::before {
|
||||
background-color: rgb(203, 147, 1);
|
||||
-webkit-mask-image: var(--icon--use-in);
|
||||
mask-image: var(--icon--use-in);
|
||||
}
|
||||
|
||||
.admonition.returned-in > ul:hover, .admonition.available-in > ul:hover, .admonition.use-in > ul:hover, .admonition.shortcuts > ul:hover {
|
||||
cursor: move;
|
||||
}
|
||||
.admonition.returned-in > ul, .admonition.available-in > ul, .admonition.use-in > ul, .admonition.shortcuts > ul {
|
||||
max-height: 200px;
|
||||
overflow-y: auto;
|
||||
}
|
||||
@@ -0,0 +1,3 @@
|
||||
.article-container h1 {
|
||||
overflow-wrap: anywhere;
|
||||
}
|
||||
@@ -0,0 +1,15 @@
|
||||
figure > img {
|
||||
height: 300px; /* resize figures so they aren't too big */
|
||||
}
|
||||
|
||||
@media (prefers-color-scheme: dark) {
|
||||
body:not([data-theme="light"]) figure > img { /* auto and dark is dark mode */
|
||||
filter: invert(92%);
|
||||
}
|
||||
}
|
||||
|
||||
@media (prefers-color-scheme: light) {
|
||||
body[data-theme="dark"] figure > img { /* auto and light is light mode */
|
||||
filter: invert(92%);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,11 @@
|
||||
.sidebar-sticky .sidebar-brand {
|
||||
flex-direction: row;
|
||||
}
|
||||
|
||||
.sidebar-sticky .sidebar-brand .sidebar-logo-container {
|
||||
align-self: center;
|
||||
}
|
||||
|
||||
.sidebar-sticky .sidebar-brand .sidebar-brand-text {
|
||||
align-self: center;
|
||||
}
|
||||
@@ -1 +1,9 @@
|
||||
.. include:: ../../CHANGES.rst
|
||||
.. _ptb-changelog:
|
||||
|
||||
=========
|
||||
Changelog
|
||||
=========
|
||||
|
||||
.. chango::
|
||||
|
||||
.. include:: ../../changes/LEGACY.rst
|
||||
+133
-290
@@ -1,27 +1,24 @@
|
||||
import inspect
|
||||
import os
|
||||
import re
|
||||
import subprocess
|
||||
import sys
|
||||
from enum import Enum
|
||||
from pathlib import Path
|
||||
from typing import Tuple
|
||||
|
||||
# If extensions (or modules to document with autodoc) are in another directory,
|
||||
# add these directories to sys.path here. If the directory is relative to the
|
||||
# documentation root, use os.path.abspath to make it absolute, like shown here.
|
||||
from docutils.nodes import Element
|
||||
from sphinx.application import Sphinx
|
||||
from sphinx.domains.python import PyXRefRole
|
||||
from sphinx.environment import BuildEnvironment
|
||||
from sphinx.util import logging
|
||||
|
||||
sys.path.insert(0, os.path.abspath("../.."))
|
||||
if sys.version_info < (3, 12):
|
||||
# Due to dependency on chango
|
||||
raise RuntimeError("This documentation needs at least Python 3.12")
|
||||
|
||||
|
||||
sys.path.insert(0, str(Path("../..").resolve().absolute()))
|
||||
|
||||
# -- General configuration ------------------------------------------------
|
||||
# General information about the project.
|
||||
project = "python-telegram-bot"
|
||||
copyright = "2015-2022, Leandro Toledo"
|
||||
copyright = "2015-2025, Leandro Toledo"
|
||||
author = "Leandro Toledo"
|
||||
|
||||
# The version info for the project you're documenting, acts as replacement for
|
||||
@@ -29,25 +26,48 @@ author = "Leandro Toledo"
|
||||
# built documents.
|
||||
#
|
||||
# The short X.Y version.
|
||||
version = "20.0a2" # telegram.__version__[:3]
|
||||
|
||||
# Import needs to be below the sys.path.insert above
|
||||
import telegram # noqa: E402
|
||||
|
||||
version = telegram.__version__
|
||||
# The full version, including alpha/beta/rc tags.
|
||||
release = "20.0a2" # telegram.__version__
|
||||
release = telegram.__version__
|
||||
|
||||
# If your documentation needs a minimal Sphinx version, state it here.
|
||||
needs_sphinx = "4.5.0"
|
||||
needs_sphinx = "8.1.3"
|
||||
|
||||
# Add any Sphinx extension module names here, as strings. They can be
|
||||
# extensions coming with Sphinx (named 'sphinx.ext.*') or your custom
|
||||
# ones.
|
||||
extensions = [
|
||||
"chango.sphinx_ext",
|
||||
"sphinx.ext.autodoc",
|
||||
"sphinx.ext.napoleon",
|
||||
"sphinx.ext.intersphinx",
|
||||
"sphinx.ext.linkcode",
|
||||
"sphinx.ext.extlinks",
|
||||
"sphinx_paramlinks",
|
||||
"sphinx_copybutton",
|
||||
"sphinx_inline_tabs",
|
||||
"sphinxcontrib.mermaid",
|
||||
"sphinx_search.extension",
|
||||
]
|
||||
|
||||
# Temporary. See #4387
|
||||
if os.environ.get("READTHEDOCS", "") == "True":
|
||||
extensions.append("sphinx_build_compatibility.extension")
|
||||
|
||||
# Configuration for the chango sphinx directive
|
||||
chango_pyproject_toml_path = Path(__file__).parent.parent.parent
|
||||
|
||||
# For shorter links to Wiki in docstrings
|
||||
extlinks = {
|
||||
"wiki": ("https://github.com/python-telegram-bot/python-telegram-bot/wiki/%s", "%s"),
|
||||
"pr": ("https://github.com/python-telegram-bot/python-telegram-bot/pull/%s", "#%s"),
|
||||
"issue": ("https://github.com/python-telegram-bot/python-telegram-bot/issues/%s", "#%s"),
|
||||
}
|
||||
|
||||
# Use intersphinx to reference the python builtin library docs
|
||||
intersphinx_mapping = {
|
||||
"python": ("https://docs.python.org/3", None),
|
||||
@@ -64,6 +84,11 @@ source_suffix = ".rst"
|
||||
# The master toctree document.
|
||||
master_doc = "index"
|
||||
|
||||
# Global substitutions
|
||||
rst_prolog = ""
|
||||
for file in Path.cwd().glob("../substitutions/*.rst"):
|
||||
rst_prolog += "\n" + file.read_text(encoding="utf-8")
|
||||
|
||||
# -- Extension settings ------------------------------------------------
|
||||
napoleon_use_admonition_for_examples = True
|
||||
|
||||
@@ -71,6 +96,14 @@ napoleon_use_admonition_for_examples = True
|
||||
# and we document the types anyway
|
||||
autodoc_typehints = "none"
|
||||
|
||||
# Show docstring for special members
|
||||
autodoc_default_options = {
|
||||
"special-members": True,
|
||||
# For some reason, __weakref__ can not be ignored by using "inherited-members" in all cases
|
||||
# so we list it here.
|
||||
"exclude-members": "__init__, __weakref__",
|
||||
}
|
||||
|
||||
# Fail on warnings & unresolved references etc
|
||||
nitpicky = True
|
||||
|
||||
@@ -87,10 +120,17 @@ linkcheck_ignore = [
|
||||
# Anchors are apparently inserted by GitHub dynamically, so let's skip checking them
|
||||
"https://github.com/python-telegram-bot/python-telegram-bot/tree/master/examples#",
|
||||
r"https://github\.com/python-telegram-bot/python-telegram-bot/wiki/[\w\-_,]+\#",
|
||||
# The LGPL license link regularly causes network errors for some reason
|
||||
re.escape("https://www.gnu.org/licenses/lgpl-3.0.html"),
|
||||
# The doc-fixes branch may not always exist - doesn't matter, we only link to it from the
|
||||
# contributing guide
|
||||
re.escape("https://docs.python-telegram-bot.org/en/doc-fixes"),
|
||||
]
|
||||
linkcheck_allowed_redirects = {
|
||||
# Redirects to the default version are okay
|
||||
r"https://docs\.python-telegram-bot\.org/.*": r"https://docs\.python-telegram-bot\.org/en/[\w\d\.]+/.*",
|
||||
r"https://docs\.python-telegram-bot\.org/.*": (
|
||||
r"https://docs\.python-telegram-bot\.org/en/[\w\d\.]+/.*"
|
||||
),
|
||||
# pre-commit.ci always redirects to the latest run
|
||||
re.escape(
|
||||
"https://results.pre-commit.ci/latest/github/python-telegram-bot/python-telegram-bot/master"
|
||||
@@ -125,71 +165,73 @@ html_theme_options = {
|
||||
"admonition-title-font-size": "0.95rem",
|
||||
"admonition-font-size": "0.92rem",
|
||||
},
|
||||
"announcement": "PTB has undergone significant changes in v20. Please read the documentation "
|
||||
"carefully and also check out the transition guide in the "
|
||||
'<a href="https://github.com/python-telegram-bot/python-telegram-bot/wiki/'
|
||||
'Transition-guide-to-Version-20.0">wiki</a>.',
|
||||
"footer_icons": [
|
||||
{
|
||||
# Telegram channel logo
|
||||
"name": "Telegram Channel",
|
||||
"url": "https://t.me/pythontelegrambotchannel/",
|
||||
# Following svg is from https://react-icons.github.io/react-icons/search?q=telegram
|
||||
"html": '<svg stroke="currentColor" fill="currentColor" stroke-width="0" '
|
||||
'viewBox="0 0 16 16" height="1em" width="1em" xmlns="http://www.w3.org/2000/svg">'
|
||||
'<path d="M16 8A8 8 0 1 1 0 8a8 8 0 0 1 16 0zM8.287 5.906c-.778.324-2.334.994'
|
||||
"-4.666 2.01-.378.15-.577.298-.595.442-.03.243.275.339.69.47l.175.055c.408.133."
|
||||
"958.288 1.243.294.26.006.549-.1.868-.32 2.179-1.471 3.304-2.214 3.374-2.23.0"
|
||||
"5-.012.12-.026.166.016.047.041.042.12.037.141-.03.129-1.227 1.241-1.846 1.81"
|
||||
"7-.193.18-.33.307-.358.336a8.154 8.154 0 0 1-.188.186c-.38.366-.664.64.015 1.08"
|
||||
"8.327.216.589.393.85.571.284.194.568.387.936.629.093.06.183.125.27.187.331.23"
|
||||
"6.63.448.997.414.214-.02.435-.22.547-.82.265-1.417.786-4.486.906-5.751a1.426 "
|
||||
"1.426 0 0 0-.013-.315.337.337 0 0 0-.114-.217.526.526 0 0 0-.31-.093c-.3.005-.7"
|
||||
'63.166-2.984 1.09z"></path></svg>',
|
||||
"html": (
|
||||
'<svg stroke="currentColor" fill="currentColor" stroke-width="0" '
|
||||
'viewBox="0 0 16 16" height="1em" width="1em" xmlns="http://www.w3.org/2000/svg">'
|
||||
'<path d="M16 8A8 8 0 1 1 0 8a8 8 0 0 1 16 0zM8.287 5.906c-.778.324-2.334.994'
|
||||
"-4.666 2.01-.378.15-.577.298-.595.442-.03.243.275.339.69.47l.175.055c.408.133."
|
||||
"958.288 1.243.294.26.006.549-.1.868-.32 2.179-1.471 3.304-2.214 3.374-2.23.0"
|
||||
"5-.012.12-.026.166.016.047.041.042.12.037.141-.03.129-1.227 1.241-1.846 1.81"
|
||||
"7-.193.18-.33.307-.358.336a8.154 8.154 0 0 1-.188.186c-.38.366-.664.64.015 1.08"
|
||||
"8.327.216.589.393.85.571.284.194.568.387.936.629.093.06.183.125.27.187.331.23"
|
||||
"6.63.448.997.414.214-.02.435-.22.547-.82.265-1.417.786-4.486.906-5.751a1.426 "
|
||||
"1.426 0 0 0-.013-.315.337.337 0 0 0-.114-.217.526.526 0 0 0-.31-.093c-.3.005-.7"
|
||||
'63.166-2.984 1.09z"></path></svg>'
|
||||
),
|
||||
"class": "",
|
||||
},
|
||||
{ # Github logo
|
||||
"name": "GitHub",
|
||||
"url": "https://github.com/python-telegram-bot/python-telegram-bot/",
|
||||
"html": '<svg stroke="currentColor" fill="currentColor" stroke-width="0" '
|
||||
'viewBox="0 0 16 16"><path fill-rule="evenodd" d="M8 0C3.58 0 0 3.58 0 8c0 3.54 '
|
||||
"2.29 6.53 5.47 7.59.4.07.55-.17.55-.38 0-.19-.01-.82-.01-1.49-2.01.37-2.53-.4"
|
||||
"9-2.69-.94-.09-.23-.48-.94-.82-1.13-.28-.15-.68-.52-.01-.53.63-.01 1.08.58 1.23"
|
||||
".82.72 1.21 1.87.87 2.33.66.07-.52.28-.87.51-1.07-1.78-.2-3.64-.89-3.64-3.95 "
|
||||
"0-.87.31-1.59.82-2.15-.08-.2-.36-1.02.08-2.12 0 0 .67-.21 2.2.82.64-.18 1.32-.2"
|
||||
"7 2-.27.68 0 1.36.09 2 .27 1.53-1.04 2.2-.82 2.2-.82.44 1.1.16 1.92.08 2.12.5"
|
||||
"1.56.82 1.27.82 2.15 0 3.07-1.87 3.75-3.65 3.95.29.25.54.73.54 1.48 0 1.07-.01 "
|
||||
'1.93-.01 2.2 0 .21.15.46.55.38A8.013 8.013 0 0 0 16 8c0-4.42-3.58-8-8-8z">'
|
||||
"</path></svg>",
|
||||
"html": (
|
||||
'<svg stroke="currentColor" fill="currentColor" stroke-width="0" '
|
||||
'viewBox="0 0 16 16"><path fill-rule="evenodd" d="M8 0C3.58 0 0 3.58 0 8c0 3.54 '
|
||||
"2.29 6.53 5.47 7.59.4.07.55-.17.55-.38 0-.19-.01-.82-.01-1.49-2.01.37-2.53-.4"
|
||||
"9-2.69-.94-.09-.23-.48-.94-.82-1.13-.28-.15-.68-.52-.01-.53.63-.01 1.08.58 1.23"
|
||||
".82.72 1.21 1.87.87 2.33.66.07-.52.28-.87.51-1.07-1.78-.2-3.64-.89-3.64-3.95 "
|
||||
"0-.87.31-1.59.82-2.15-.08-.2-.36-1.02.08-2.12 0 0 .67-.21 2.2.82.64-.18 1.32-.2"
|
||||
"7 2-.27.68 0 1.36.09 2 .27 1.53-1.04 2.2-.82 2.2-.82.44 1.1.16 1.92.08 2.12.5"
|
||||
"1.56.82 1.27.82 2.15 0 3.07-1.87 3.75-3.65 3.95.29.25.54.73.54 1.48 0 1.07-.01 "
|
||||
'1.93-.01 2.2 0 .21.15.46.55.38A8.013 8.013 0 0 0 16 8c0-4.42-3.58-8-8-8z">'
|
||||
"</path></svg>"
|
||||
),
|
||||
"class": "",
|
||||
},
|
||||
{ # PTB website logo - globe
|
||||
"name": "python-telegram-bot website",
|
||||
"url": "https://python-telegram-bot.org/",
|
||||
"html": '<svg stroke="currentColor" fill="currentColor" stroke-width="0" '
|
||||
'viewBox="0 0 16 16" height="1em" width="1em" xmlns="http://www.w3.org/2000/svg">'
|
||||
'<path d="M0 8a8 8 0 1 1 16 0A8 8 0 0 1 0 8zm7.5-6.923c-.67.204-1.335.82-1.887 '
|
||||
"1.855-.143.268-.276.56-.395.872.705.157 1.472.257 2.282.287V1.077zM4.249 3.53"
|
||||
"9c.142-.384.304-.744.481-1.078a6.7 6.7 0 0 1 .597-.933A7.01 7.01 0 0 0 3.051 "
|
||||
"3.05c.362.184.763.349 1.198.49zM3.509 7.5c.036-1.07.188-2.087.436-3.008a9.124 "
|
||||
"9.124 0 0 1-1.565-.667A6.964 6.964 0 0 0 1.018 7.5h2.49zm1.4-2.741a12.344 "
|
||||
"12.344 0 0 0-.4 2.741H7.5V5.091c-.91-.03-1.783-.145-2.591-.332zM8.5 5.09V7.5h"
|
||||
"2.99a12.342 12.342 0 0 0-.399-2.741c-.808.187-1.681.301-2.591.332zM4.51 8.5c.03"
|
||||
"5.987.176 1.914.399 2.741A13.612 13.612 0 0 1 7.5 10.91V8.5H4.51zm3.99 0v2.409"
|
||||
"c.91.03 1.783.145 2.591.332.223-.827.364-1.754.4-2.741H8.5zm-3.282 3.696c.12.31"
|
||||
"2.252.604.395.872.552 1.035 1.218 1.65 1.887 1.855V11.91c-.81.03-1.577.13-2.28"
|
||||
"2.287zm.11 2.276a6.696 6.696 0 0 1-.598-.933 8.853 8.853 0 0 1-.481-1.079 8.38 "
|
||||
"8.38 0 0 0-1.198.49 7.01 7.01 0 0 0 2.276 1.522zm-1.383-2.964A13.36 13.36 0 0 1"
|
||||
" 3.508 8.5h-2.49a6.963 6.963 0 0 0 1.362 3.675c.47-.258.995-.482 1.565-.667zm"
|
||||
"6.728 2.964a7.009 7.009 0 0 0 2.275-1.521 8.376 8.376 0 0 0-1.197-.49 8.853 "
|
||||
"8.853 0 0 1-.481 1.078 6.688 6.688 0 0 1-.597.933zM8.5 11.909v3.014c.67-.204 "
|
||||
"1.335-.82 1.887-1.855.143-.268.276-.56.395-.872A12.63 12.63 0 0 0 8.5 11.91zm"
|
||||
"3.555-.401c.57.185 1.095.409 1.565.667A6.963 6.963 0 0 0 14.982 8.5h-2.49a1"
|
||||
"3.36 13.36 0 0 1-.437 3.008zM14.982 7.5a6.963 6.963 0 0 0-1.362-3.675c-.47.25"
|
||||
"8-.995.482-1.565.667.248.92.4 1.938.437 3.008h2.49zM11.27 2.461c.177.334.339.6"
|
||||
"94.482 1.078a8.368 8.368 0 0 0 1.196-.49 7.01 7.01 0 0 0-2.275-1.52c.218.283.4"
|
||||
"18.597.597.932zm-.488 1.343a7.765 7.765 0 0 0-.395-.872C9.835 1.897 9.17 1.282 "
|
||||
'8.5 1.077V4.09c.81-.03 1.577-.13 2.282-.287z"></path></svg>',
|
||||
"html": (
|
||||
'<svg stroke="currentColor" fill="currentColor" stroke-width="0" '
|
||||
'viewBox="0 0 16 16" height="1em" width="1em" xmlns="http://www.w3.org/2000/svg">'
|
||||
'<path d="M0 8a8 8 0 1 1 16 0A8 8 0 0 1 0 8zm7.5-6.923c-.67.204-1.335.82-1.887 '
|
||||
"1.855-.143.268-.276.56-.395.872.705.157 1.472.257 2.282.287V1.077zM4.249 3.53"
|
||||
"9c.142-.384.304-.744.481-1.078a6.7 6.7 0 0 1 .597-.933A7.01 7.01 0 0 0 3.051 "
|
||||
"3.05c.362.184.763.349 1.198.49zM3.509 7.5c.036-1.07.188-2.087.436-3.008a9.124 "
|
||||
"9.124 0 0 1-1.565-.667A6.964 6.964 0 0 0 1.018 7.5h2.49zm1.4-2.741a12.344 "
|
||||
"12.344 0 0 0-.4 2.741H7.5V5.091c-.91-.03-1.783-.145-2.591-.332zM8.5 5.09V7.5h"
|
||||
"2.99a12.342 12.342 0 0 0-.399-2.741c-.808.187-1.681.301-2.591.332zM4.51 8.5c.03"
|
||||
"5.987.176 1.914.399 2.741A13.612 13.612 0 0 1 7.5 10.91V8.5H4.51zm3.99 0v2.409"
|
||||
"c.91.03 1.783.145 2.591.332.223-.827.364-1.754.4-2.741H8.5zm-3.282 3.696c.12.31"
|
||||
"2.252.604.395.872.552 1.035 1.218 1.65 1.887 1.855V11.91c-.81.03-1.577.13-2.28"
|
||||
"2.287zm.11 2.276a6.696 6.696 0 0 1-.598-.933 8.853 8.853 0 0 1-.481-1.079 8.38 "
|
||||
"8.38 0 0 0-1.198.49 7.01 7.01 0 0 0 2.276 1.522zm-1.383-2.964A13.36 13.36 0 0 1"
|
||||
" 3.508 8.5h-2.49a6.963 6.963 0 0 0 1.362 3.675c.47-.258.995-.482 1.565-.667zm"
|
||||
"6.728 2.964a7.009 7.009 0 0 0 2.275-1.521 8.376 8.376 0 0 0-1.197-.49 8.853 "
|
||||
"8.853 0 0 1-.481 1.078 6.688 6.688 0 0 1-.597.933zM8.5 11.909v3.014c.67-.204 "
|
||||
"1.335-.82 1.887-1.855.143-.268.276-.56.395-.872A12.63 12.63 0 0 0 8.5 11.91zm"
|
||||
"3.555-.401c.57.185 1.095.409 1.565.667A6.963 6.963 0 0 0 14.982 8.5h-2.49a1"
|
||||
"3.36 13.36 0 0 1-.437 3.008zM14.982 7.5a6.963 6.963 0 0 0-1.362-3.675c-.47.25"
|
||||
"8-.995.482-1.565.667.248.92.4 1.938.437 3.008h2.49zM11.27 2.461c.177.334.339.6"
|
||||
"94.482 1.078a8.368 8.368 0 0 0 1.196-.49 7.01 7.01 0 0 0-2.275-1.52c.218.283.4"
|
||||
"18.597.597.932zm-.488 1.343a7.765 7.765 0 0 0-.395-.872C9.835 1.897 9.17 1.282 "
|
||||
'8.5 1.077V4.09c.81-.03 1.577-.13 2.282-.287z"></path></svg>'
|
||||
),
|
||||
"class": "",
|
||||
},
|
||||
],
|
||||
@@ -215,15 +257,27 @@ html_static_path = ["_static"]
|
||||
html_css_files = [
|
||||
"style_external_link.css",
|
||||
"style_mermaid_diagrams.css",
|
||||
"style_sidebar_brand.css",
|
||||
"style_general.css",
|
||||
"style_admonitions.css",
|
||||
"style_images.css",
|
||||
]
|
||||
html_permalinks_icon = "¶" # Furo's default permalink icon is `#`` which doesn't look great imo.
|
||||
|
||||
html_permalinks_icon = "¶" # Furo's default permalink icon is `#` which doesn't look great imo.
|
||||
|
||||
# Output file base name for HTML help builder.
|
||||
htmlhelp_basename = "python-telegram-bot-doc"
|
||||
|
||||
# The base URL which points to the root of the HTML documentation. It is used to indicate the
|
||||
# location of document using The Canonical Link Relation. Default: ''.
|
||||
html_baseurl = "https://docs.python-telegram-bot.org"
|
||||
# Set canonical URL from the Read the Docs Domain
|
||||
html_baseurl = os.environ.get("READTHEDOCS_CANONICAL_URL", "")
|
||||
|
||||
# Tell Jinja2 templates the build is running on Read the Docs
|
||||
html_context = {}
|
||||
if os.environ.get("READTHEDOCS", "") == "True":
|
||||
html_context["READTHEDOCS"] = True
|
||||
|
||||
|
||||
# -- Options for LaTeX output ---------------------------------------------
|
||||
|
||||
@@ -257,6 +311,7 @@ latex_logo = "ptb-logo_1024.png"
|
||||
# (source start file, name, description, authors, manual section).
|
||||
man_pages = [(master_doc, "python-telegram-bot", "python-telegram-bot Documentation", [author], 1)]
|
||||
|
||||
# rtd_sphinx_search_file_type = "un-minified" # Configuration for furo-sphinx-search
|
||||
|
||||
# -- Options for Texinfo output -------------------------------------------
|
||||
|
||||
@@ -277,235 +332,23 @@ texinfo_documents = [
|
||||
|
||||
# -- script stuff --------------------------------------------------------
|
||||
|
||||
# get the sphinx(!) logger
|
||||
# Makes sure logs render in red and also plays nicely with e.g. the `nitpicky` option.
|
||||
sphinx_logger = logging.getLogger(__name__)
|
||||
# Due to Sphinx behaviour, these imports only work when imported here, not at top of module.
|
||||
|
||||
CONSTANTS_ROLE = "tg-const"
|
||||
import telegram # We need this so that the `eval` below works
|
||||
|
||||
|
||||
class TGConstXRefRole(PyXRefRole):
|
||||
"""This is a bit of Sphinx magic. We add a new role type called tg-const that allows us to
|
||||
reference values from the `telegram.constants.module` while using the actual value as title
|
||||
of the link.
|
||||
|
||||
Example:
|
||||
|
||||
:tg-const:`telegram.constants.MessageLimit.TEXT_LENGTH` renders as `4096` but links to the
|
||||
constant.
|
||||
"""
|
||||
|
||||
def process_link(
|
||||
self,
|
||||
env: BuildEnvironment,
|
||||
refnode: Element,
|
||||
has_explicit_title: bool,
|
||||
title: str,
|
||||
target: str,
|
||||
) -> Tuple[str, str]:
|
||||
title, target = super().process_link(env, refnode, has_explicit_title, title, target)
|
||||
try:
|
||||
# We use `eval` to get the value of the expression. Maybe there are better ways to
|
||||
# do this via importlib or so, but it does the job for now
|
||||
value = eval(target)
|
||||
# Maybe we need a better check if the target is actually from tg.constants
|
||||
# for now checking if it's an Enum suffices since those are used nowhere else in PTB
|
||||
if isinstance(value, Enum):
|
||||
# Special casing for file size limits
|
||||
if isinstance(value, telegram.constants.FileSizeLimit):
|
||||
return f"{int(value.value / 1e6)} MB", target
|
||||
return repr(value.value), target
|
||||
# Just for (Bot API) versions number auto add in constants:
|
||||
if isinstance(value, str) and target in (
|
||||
"telegram.constants.BOT_API_VERSION",
|
||||
"telegram.__version__",
|
||||
):
|
||||
return value, target
|
||||
if isinstance(value, tuple) and target in (
|
||||
"telegram.constants.BOT_API_VERSION_INFO",
|
||||
"telegram.__version_info__",
|
||||
):
|
||||
return repr(value), target
|
||||
sphinx_logger.warning(
|
||||
f"%s:%d: WARNING: Did not convert reference %s. :{CONSTANTS_ROLE}: is not supposed"
|
||||
" to be used with this type of target.",
|
||||
refnode.source,
|
||||
refnode.line,
|
||||
refnode.rawsource,
|
||||
)
|
||||
return title, target
|
||||
except Exception as exc:
|
||||
sphinx_logger.exception(
|
||||
f"%s:%d: WARNING: Did not convert reference %s due to an exception.",
|
||||
refnode.source,
|
||||
refnode.line,
|
||||
refnode.rawsource,
|
||||
exc_info=exc,
|
||||
)
|
||||
return title, target
|
||||
|
||||
|
||||
def autodoc_skip_member(app, what, name, obj, skip, options):
|
||||
"""We use this to not document certain members like filter() or check_update() for filters.
|
||||
See https://www.sphinx-doc.org/en/master/usage/extensions/autodoc.html#skipping-members"""
|
||||
|
||||
included = {"MessageFilter", "UpdateFilter"} # filter() and check_update() only for these.
|
||||
included_in_obj = any(inc in repr(obj) for inc in included)
|
||||
|
||||
if included_in_obj: # it's difficult to see if check_update is from an inherited-member or not
|
||||
for frame in inspect.stack(): # From https://github.com/sphinx-doc/sphinx/issues/9533
|
||||
if frame.function == "filter_members":
|
||||
docobj = frame.frame.f_locals["self"].object
|
||||
if not any(inc in str(docobj) for inc in included) and name == "check_update":
|
||||
return True
|
||||
break
|
||||
|
||||
if name == "filter" and obj.__module__ == "telegram.ext.filters":
|
||||
if not included_in_obj:
|
||||
return True # return True to exclude from docs.
|
||||
|
||||
|
||||
# ------------------------------------------------------------------------------------------------
|
||||
# This part is for getting the [source] links on the classes, methods etc link to the correct
|
||||
# files & lines on github. Can be simplified once https://github.com/sphinx-doc/sphinx/issues/1556
|
||||
# is closed
|
||||
|
||||
line_numbers = {}
|
||||
file_root = Path(inspect.getsourcefile(telegram)).parent.parent.resolve()
|
||||
import telegram.ext # Needed for checking if an object is a BaseFilter
|
||||
|
||||
|
||||
def autodoc_process_docstring(app: Sphinx, what, name: str, obj: object, options, lines):
|
||||
"""We misuse this autodoc hook to get the file names & line numbers because we have access
|
||||
to the actual object here.
|
||||
"""
|
||||
# Ce can't properly handle ordinary attributes.
|
||||
# In linkcode_resolve we'll resolve to the `__init__` or module instead
|
||||
if what == "attribute":
|
||||
return
|
||||
|
||||
# Special casing for properties
|
||||
if hasattr(obj, "fget"):
|
||||
obj = obj.fget
|
||||
|
||||
# Special casing for filters
|
||||
if isinstance(obj, telegram.ext.filters.BaseFilter):
|
||||
obj = obj.__class__
|
||||
|
||||
try:
|
||||
source_lines, start_line = inspect.getsourcelines(obj)
|
||||
end_line = start_line + len(source_lines)
|
||||
file = Path(inspect.getsourcefile(obj)).relative_to(file_root)
|
||||
line_numbers[name] = (file, start_line, end_line)
|
||||
except Exception:
|
||||
pass
|
||||
|
||||
# Since we don't document the `__init__`, we call this manually to have it available for
|
||||
# attributes -- see the note above
|
||||
if what == "class":
|
||||
autodoc_process_docstring(app, "method", f"{name}.__init__", obj.__init__, options, lines)
|
||||
|
||||
|
||||
def _git_branch() -> str:
|
||||
"""Get's the current git sha if available or fall back to `master`"""
|
||||
try:
|
||||
output = subprocess.check_output( # skipcq: BAN-B607
|
||||
["git", "describe", "--tags", "--always"], stderr=subprocess.STDOUT
|
||||
)
|
||||
return output.decode().strip()
|
||||
except Exception as exc:
|
||||
sphinx_logger.exception(
|
||||
f"Failed to get a description of the current commit. Falling back to `master`.",
|
||||
exc_info=exc,
|
||||
)
|
||||
return "master"
|
||||
|
||||
|
||||
git_branch = _git_branch()
|
||||
base_url = "https://github.com/python-telegram-bot/python-telegram-bot/blob/"
|
||||
|
||||
|
||||
def linkcode_resolve(_, info):
|
||||
"""See www.sphinx-doc.org/en/master/usage/extensions/linkcode.html"""
|
||||
combined = ".".join((info["module"], info["fullname"]))
|
||||
# special casing for ExtBot which is due to the special structure of extbot.rst
|
||||
combined = combined.replace("ExtBot.ExtBot", "ExtBot")
|
||||
|
||||
line_info = line_numbers.get(combined)
|
||||
|
||||
if not line_info:
|
||||
# Try the __init__
|
||||
line_info = line_numbers.get(f"{combined.rsplit('.', 1)[0]}.__init__")
|
||||
if not line_info:
|
||||
# Try the class
|
||||
line_info = line_numbers.get(f"{combined.rsplit('.', 1)[0]}")
|
||||
if not line_info:
|
||||
# Try the module
|
||||
line_info = line_numbers.get(info["module"])
|
||||
|
||||
if not line_info:
|
||||
return
|
||||
|
||||
file, start_line, end_line = line_info
|
||||
return f"{base_url}{git_branch}/{file}#L{start_line}-L{end_line}"
|
||||
|
||||
|
||||
# End of logic for the [source] links
|
||||
# ------------------------------------------------------------------------------------------------
|
||||
|
||||
|
||||
# Some base classes are implementation detail
|
||||
# We want to instead show *their* base class
|
||||
PRIVATE_BASE_CLASSES = {
|
||||
"_ChatUserBaseFilter": "MessageFilter",
|
||||
"_Dice": "MessageFilter",
|
||||
"_BaseThumbedMedium": "TelegramObject",
|
||||
"_BaseMedium": "TelegramObject",
|
||||
"_CredentialsBase": "TelegramObject",
|
||||
}
|
||||
|
||||
|
||||
def autodoc_process_bases(app, name, obj, option, bases: list):
|
||||
"""Here we fine tune how the base class's classes are displayed."""
|
||||
for idx, base in enumerate(bases):
|
||||
# let's use a string representation of the object
|
||||
base = str(base)
|
||||
|
||||
# Special case because base classes are in std lib:
|
||||
if "StringEnum" in base == "<enum 'StringEnum'>":
|
||||
bases[idx] = ":class:`enum.Enum`"
|
||||
bases.insert(0, ":class:`str`")
|
||||
continue
|
||||
|
||||
# Drop generics (at least for now)
|
||||
if base.endswith("]"):
|
||||
base = base.split("[", maxsplit=1)[0]
|
||||
bases[idx] = f":class:`{base}`"
|
||||
|
||||
# Now convert `telegram._message.Message` to `telegram.Message` etc
|
||||
match = re.search(pattern=r"(telegram(\.ext|))\.[_\w\.]+", string=base)
|
||||
if not match or "_utils" in base:
|
||||
return
|
||||
|
||||
parts = match.group(0).split(".")
|
||||
|
||||
# Remove private paths
|
||||
for index, part in enumerate(parts):
|
||||
if part.startswith("_"):
|
||||
parts = parts[:index] + parts[-1:]
|
||||
break
|
||||
|
||||
# Replace private base classes with their respective parent
|
||||
parts = [PRIVATE_BASE_CLASSES.get(part, part) for part in parts]
|
||||
|
||||
base = ".".join(parts)
|
||||
|
||||
bases[idx] = f":class:`{base}`"
|
||||
# Not used but must be imported for the linkcode extension to find it
|
||||
from docs.auxil.link_code import linkcode_resolve # noqa: E402, F401
|
||||
from docs.auxil.sphinx_hooks import ( # noqa: E402
|
||||
autodoc_process_bases,
|
||||
autodoc_process_docstring,
|
||||
autodoc_skip_member,
|
||||
)
|
||||
from docs.auxil.tg_const_role import CONSTANTS_ROLE, TGConstXRefRole # noqa: E402
|
||||
|
||||
|
||||
def setup(app: Sphinx):
|
||||
app.connect("autodoc-skip-member", autodoc_skip_member)
|
||||
app.connect("autodoc-process-bases", autodoc_process_bases)
|
||||
app.connect("autodoc-process-docstring", autodoc_process_docstring)
|
||||
# The default priority is 500. We want our function to run before napoleon doc-conversion
|
||||
# and sphinx-paramlinks do, b/c otherwise the inserted kwargs in the bot methods won't show
|
||||
# up in the objects.inv file that Sphinx generates (i.e. not in the search).
|
||||
app.connect("autodoc-process-docstring", autodoc_process_docstring, priority=100)
|
||||
app.add_role_to_domain("py", CONSTANTS_ROLE, TGConstXRefRole())
|
||||
|
||||
@@ -1,7 +1,43 @@
|
||||
``customwebhookbot.py``
|
||||
=======================
|
||||
|
||||
.. literalinclude:: ../../examples/customwebhookbot.py
|
||||
:language: python
|
||||
:linenos:
|
||||
This example is available for different web frameworks.
|
||||
You can select your preferred framework by opening one of the tabs above the code example.
|
||||
|
||||
.. hint::
|
||||
|
||||
The following examples show how different Python web frameworks can be used alongside PTB.
|
||||
This can be useful for two use cases:
|
||||
|
||||
1. For extending the functionality of your existing bot to handling updates of external services
|
||||
2. For extending the functionality of your exisiting web application to also include chat bot functionality
|
||||
|
||||
How the PTB and web framework components of the examples below are viewed surely depends on which use case one has in mind.
|
||||
We are fully aware that a combination of PTB with web frameworks will always mean finding a tradeoff between usability and best practices for both PTB and the web framework and these examples are certainly far from optimal solutions.
|
||||
Please understand them as starting points and use your expertise of the web framework of your choosing to build up on them.
|
||||
You are of course also very welcome to help improve these examples!
|
||||
|
||||
.. tab:: ``starlette``
|
||||
|
||||
.. literalinclude:: ../../examples/customwebhookbot/starlettebot.py
|
||||
:language: python
|
||||
:linenos:
|
||||
|
||||
.. tab:: ``flask``
|
||||
|
||||
.. literalinclude:: ../../examples/customwebhookbot/flaskbot.py
|
||||
:language: python
|
||||
:linenos:
|
||||
|
||||
.. tab:: ``quart``
|
||||
|
||||
.. literalinclude:: ../../examples/customwebhookbot/quartbot.py
|
||||
:language: python
|
||||
:linenos:
|
||||
|
||||
.. tab:: ``Django``
|
||||
|
||||
.. literalinclude:: ../../examples/customwebhookbot/djangobot.py
|
||||
:language: python
|
||||
:linenos:
|
||||
|
||||
@@ -8,7 +8,7 @@ aspect of the Telegram Bot API while others focus on one of the
|
||||
mechanics of this library. Except for the
|
||||
:any:`examples.rawapibot` example, they all use the high-level
|
||||
framework this library provides with the
|
||||
:any:`telegram.ext <telegram.ext>` submodule.
|
||||
:mod:`telegram.ext` submodule.
|
||||
|
||||
All examples are licensed under the `CC0
|
||||
License <https://github.com/python-telegram-bot/python-telegram-bot/blob/master/examples/LICENSE.txt>`__
|
||||
@@ -38,8 +38,8 @@ class to send timed messages. The user sets a timer by using ``/set``
|
||||
command with a specific time, for example ``/set 30``. The bot then sets
|
||||
up a job to send a message to that user after 30 seconds. The user can
|
||||
also cancel the timer by sending ``/unset``. To learn more about the
|
||||
``JobQueue``, read `this wiki
|
||||
article <https://github.com/python-telegram-bot/python-telegram-bot/wiki/Extensions-%E2%80%93-JobQueue>`__.
|
||||
``JobQueue``, read `this wiki article <https://github.com/python-telegram-bot/python-telegram-bot/wiki/Extensions---JobQueue>`__.
|
||||
Note: To use ``JobQueue``, you must install PTB via ``pip install "python-telegram-bot[job-queue]"``
|
||||
|
||||
:any:`examples.conversationbot`
|
||||
-------------------------------
|
||||
@@ -49,7 +49,7 @@ this library, we introduced the
|
||||
:class:`telegram.ext.ConversationHandler`
|
||||
for that exact purpose. This example uses it to retrieve
|
||||
user-information in a conversation-like style. To get a better
|
||||
understanding, take a look at the :ref:`state diagrem <conversationbot-diagram>`.
|
||||
understanding, take a look at the :ref:`state diagram <conversationbot-diagram>`.
|
||||
|
||||
:any:`examples.conversationbot2`
|
||||
--------------------------------
|
||||
@@ -115,6 +115,7 @@ Don’t forget to enable and configure payments with
|
||||
`@BotFather <https://telegram.me/BotFather>`_. Check out this
|
||||
`guide <https://github.com/python-telegram-bot/python-telegram-bot/wiki/Telegram-Passport>`__
|
||||
on Telegram passports in PTB.
|
||||
Note: To use Telegram Passport, you must install PTB via ``pip install "python-telegram-bot[passport]"``
|
||||
|
||||
:any:`examples.paymentbot`
|
||||
--------------------------
|
||||
@@ -162,6 +163,7 @@ combination with ``telegram.ext.Application``.
|
||||
|
||||
This example showcases how PTBs “arbitrary callback data” feature can be
|
||||
used.
|
||||
Note: To use arbitrary callback data, you must install PTB via ``pip install "python-telegram-bot[callback-data]"``
|
||||
|
||||
Pure API
|
||||
--------
|
||||
|
||||
@@ -0,0 +1,9 @@
|
||||
.. tip::
|
||||
* When combining ``python-telegram-bot`` with other :mod:`asyncio` based frameworks, using this
|
||||
method is likely not the best choice, as it blocks the event loop until it receives a stop
|
||||
signal as described above.
|
||||
Instead, you can manually call the methods listed below to start and shut down the application
|
||||
and the :attr:`~telegram.ext.Application.updater`.
|
||||
Keeping the event loop running and listening for a stop signal is then up to you.
|
||||
* To gracefully stop the execution of this method from within a handler, job or error callback,
|
||||
use :meth:`~telegram.ext.Application.stop_running`.
|
||||
@@ -25,6 +25,8 @@
|
||||
- Used for sending documents
|
||||
* - :meth:`~telegram.Bot.send_game`
|
||||
- Used for sending a game
|
||||
* - :meth:`~telegram.Bot.send_gift`
|
||||
- Used for sending a gift
|
||||
* - :meth:`~telegram.Bot.send_invoice`
|
||||
- Used for sending an invoice
|
||||
* - :meth:`~telegram.Bot.send_location`
|
||||
@@ -33,6 +35,8 @@
|
||||
- Used for sending media grouped together
|
||||
* - :meth:`~telegram.Bot.send_message`
|
||||
- Used for sending text messages
|
||||
* - :meth:`~telegram.Bot.send_paid_media`
|
||||
- Used for sending paid media to channels
|
||||
* - :meth:`~telegram.Bot.send_photo`
|
||||
- Used for sending photos
|
||||
* - :meth:`~telegram.Bot.send_poll`
|
||||
@@ -49,8 +53,12 @@
|
||||
- Used for sending voice messages
|
||||
* - :meth:`~telegram.Bot.copy_message`
|
||||
- Used for copying the contents of an arbitrary message
|
||||
* - :meth:`~telegram.Bot.copy_messages`
|
||||
- Used for copying the contents of an multiple arbitrary messages
|
||||
* - :meth:`~telegram.Bot.forward_message`
|
||||
- Used for forwarding messages
|
||||
* - :meth:`~telegram.Bot.forward_messages`
|
||||
- Used for forwarding multiple messages at once
|
||||
|
||||
.. raw:: html
|
||||
|
||||
@@ -76,6 +84,10 @@
|
||||
- Used for answering a shipping query
|
||||
* - :meth:`~telegram.Bot.answer_web_app_query`
|
||||
- Used for answering a web app query
|
||||
* - :meth:`~telegram.Bot.delete_message`
|
||||
- Used for deleting messages.
|
||||
* - :meth:`~telegram.Bot.delete_messages`
|
||||
- Used for deleting multiple messages as once.
|
||||
* - :meth:`~telegram.Bot.edit_message_caption`
|
||||
- Used for editing captions
|
||||
* - :meth:`~telegram.Bot.edit_message_media`
|
||||
@@ -88,8 +100,8 @@
|
||||
- Used for editing text messages
|
||||
* - :meth:`~telegram.Bot.stop_poll`
|
||||
- Used for stopping the running poll
|
||||
* - :meth:`~telegram.Bot.delete_message`
|
||||
- Used for deleting messages.
|
||||
* - :meth:`~telegram.Bot.set_message_reaction`
|
||||
- Used for setting reactions on messages
|
||||
|
||||
.. raw:: html
|
||||
|
||||
@@ -105,6 +117,10 @@
|
||||
:align: left
|
||||
:widths: 1 4
|
||||
|
||||
* - :meth:`~telegram.Bot.approve_chat_join_request`
|
||||
- Used for approving a chat join request
|
||||
* - :meth:`~telegram.Bot.decline_chat_join_request`
|
||||
- Used for declining a chat join request
|
||||
* - :meth:`~telegram.Bot.ban_chat_member`
|
||||
- Used for banning a member from the chat
|
||||
* - :meth:`~telegram.Bot.unban_chat_member`
|
||||
@@ -129,10 +145,6 @@
|
||||
- Used for editing a non-primary invite link
|
||||
* - :meth:`~telegram.Bot.revoke_chat_invite_link`
|
||||
- Used for revoking an invite link created by the bot
|
||||
* - :meth:`~telegram.Bot.approve_chat_join_request`
|
||||
- Used for approving a chat join request
|
||||
* - :meth:`~telegram.Bot.decline_chat_join_request`
|
||||
- Used for declining a chat join request
|
||||
* - :meth:`~telegram.Bot.set_chat_photo`
|
||||
- Used for setting a photo to a chat
|
||||
* - :meth:`~telegram.Bot.delete_chat_photo`
|
||||
@@ -141,12 +153,16 @@
|
||||
- Used for setting a chat title
|
||||
* - :meth:`~telegram.Bot.set_chat_description`
|
||||
- Used for setting the description of a chat
|
||||
* - :meth:`~telegram.Bot.set_user_emoji_status`
|
||||
- Used for setting the users status emoji
|
||||
* - :meth:`~telegram.Bot.pin_chat_message`
|
||||
- Used for pinning a message
|
||||
* - :meth:`~telegram.Bot.unpin_chat_message`
|
||||
- Used for unpinning a message
|
||||
* - :meth:`~telegram.Bot.unpin_all_chat_messages`
|
||||
- Used for unpinning all pinned chat messages
|
||||
* - :meth:`~telegram.Bot.get_business_connection`
|
||||
- Used for getting information about the business account.
|
||||
* - :meth:`~telegram.Bot.get_user_profile_photos`
|
||||
- Used for obtaining user's profile pictures
|
||||
* - :meth:`~telegram.Bot.get_chat`
|
||||
@@ -157,6 +173,48 @@
|
||||
- Used for getting the number of members in a chat
|
||||
* - :meth:`~telegram.Bot.get_chat_member`
|
||||
- Used for getting a member of a chat
|
||||
* - :meth:`~telegram.Bot.get_user_chat_boosts`
|
||||
- Used for getting the list of boosts added to a chat
|
||||
* - :meth:`~telegram.Bot.leave_chat`
|
||||
- Used for leaving a chat
|
||||
|
||||
.. raw:: html
|
||||
|
||||
</details>
|
||||
<br>
|
||||
|
||||
.. raw:: html
|
||||
|
||||
<details>
|
||||
<summary>Verification on behalf of an organization</summary>
|
||||
|
||||
.. list-table::
|
||||
:align: left
|
||||
:widths: 1 4
|
||||
|
||||
* - :meth:`~telegram.Bot.verify_chat`
|
||||
- Used for verifying a chat
|
||||
* - :meth:`~telegram.Bot.verify_user`
|
||||
- Used for verifying a user
|
||||
* - :meth:`~telegram.Bot.remove_chat_verification`
|
||||
- Used for removing the verification from a chat
|
||||
* - :meth:`~telegram.Bot.remove_user_verification`
|
||||
- Used for removing the verification from a user
|
||||
|
||||
.. raw:: html
|
||||
|
||||
</details>
|
||||
<br>
|
||||
|
||||
.. raw:: html
|
||||
|
||||
<details>
|
||||
<summary>Bot settings</summary>
|
||||
|
||||
.. list-table::
|
||||
:align: left
|
||||
:widths: 1 4
|
||||
|
||||
* - :meth:`~telegram.Bot.set_my_commands`
|
||||
- Used for setting the list of commands
|
||||
* - :meth:`~telegram.Bot.delete_my_commands`
|
||||
@@ -171,8 +229,18 @@
|
||||
- Used for obtaining the menu button of a private chat or the default menu button
|
||||
* - :meth:`~telegram.Bot.set_chat_menu_button`
|
||||
- Used for setting the menu button of a private chat or the default menu button
|
||||
* - :meth:`~telegram.Bot.leave_chat`
|
||||
- Used for leaving a chat
|
||||
* - :meth:`~telegram.Bot.set_my_description`
|
||||
- Used for setting the description of the bot
|
||||
* - :meth:`~telegram.Bot.get_my_description`
|
||||
- Used for obtaining the description of the bot
|
||||
* - :meth:`~telegram.Bot.set_my_short_description`
|
||||
- Used for setting the short description of the bot
|
||||
* - :meth:`~telegram.Bot.get_my_short_description`
|
||||
- Used for obtaining the short description of the bot
|
||||
* - :meth:`~telegram.Bot.set_my_name`
|
||||
- Used for setting the name of the bot
|
||||
* - :meth:`~telegram.Bot.get_my_name`
|
||||
- Used for obtaining the name of the bot
|
||||
|
||||
.. raw:: html
|
||||
|
||||
@@ -194,18 +262,34 @@
|
||||
- Used for deleting a sticker from a set
|
||||
* - :meth:`~telegram.Bot.create_new_sticker_set`
|
||||
- Used for creating a new sticker set
|
||||
* - :meth:`~telegram.Bot.delete_sticker_set`
|
||||
- Used for deleting a sticker set made by a bot
|
||||
* - :meth:`~telegram.Bot.set_chat_sticker_set`
|
||||
- Used for setting a sticker set
|
||||
- Used for setting a sticker set of a chat
|
||||
* - :meth:`~telegram.Bot.delete_chat_sticker_set`
|
||||
- Used for deleting the set sticker set
|
||||
- Used for deleting the set sticker set of a chat
|
||||
* - :meth:`~telegram.Bot.replace_sticker_in_set`
|
||||
- Used for replacing a sticker in a set
|
||||
* - :meth:`~telegram.Bot.set_sticker_position_in_set`
|
||||
- Used for moving a sticker's position in the set
|
||||
* - :meth:`~telegram.Bot.set_sticker_set_thumb`
|
||||
* - :meth:`~telegram.Bot.set_sticker_set_title`
|
||||
- Used for setting the title of a sticker set
|
||||
* - :meth:`~telegram.Bot.set_sticker_emoji_list`
|
||||
- Used for setting the emoji list of a sticker
|
||||
* - :meth:`~telegram.Bot.set_sticker_keywords`
|
||||
- Used for setting the keywords of a sticker
|
||||
* - :meth:`~telegram.Bot.set_sticker_mask_position`
|
||||
- Used for setting the mask position of a mask sticker
|
||||
* - :meth:`~telegram.Bot.set_sticker_set_thumbnail`
|
||||
- Used for setting the thumbnail of a sticker set
|
||||
* - :meth:`~telegram.Bot.set_custom_emoji_sticker_set_thumbnail`
|
||||
- Used for setting the thumbnail of a custom emoji sticker set
|
||||
* - :meth:`~telegram.Bot.get_sticker_set`
|
||||
- Used for getting a sticker set
|
||||
* - :meth:`~telegram.Bot.upload_sticker_file`
|
||||
- Used for uploading a sticker file
|
||||
* - :meth:`~telegram.Bot.get_custom_emoji_stickers`
|
||||
- Used for getting custom emoji files based on their IDs
|
||||
|
||||
.. raw:: html
|
||||
|
||||
@@ -257,7 +341,48 @@
|
||||
.. raw:: html
|
||||
|
||||
<details>
|
||||
<summary>Miscellaneous</summary>
|
||||
<summary>Forum topic management</summary>
|
||||
|
||||
.. list-table::
|
||||
:align: left
|
||||
:widths: 1 4
|
||||
|
||||
* - :meth:`~telegram.Bot.close_forum_topic`
|
||||
- Used for closing a forum topic
|
||||
* - :meth:`~telegram.Bot.close_general_forum_topic`
|
||||
- Used for closing the general forum topic
|
||||
* - :meth:`~telegram.Bot.create_forum_topic`
|
||||
- Used to create a topic
|
||||
* - :meth:`~telegram.Bot.delete_forum_topic`
|
||||
- Used for deleting a forum topic
|
||||
* - :meth:`~telegram.Bot.edit_forum_topic`
|
||||
- Used to edit a topic
|
||||
* - :meth:`~telegram.Bot.edit_general_forum_topic`
|
||||
- Used to edit the general topic
|
||||
* - :meth:`~telegram.Bot.get_forum_topic_icon_stickers`
|
||||
- Used to get custom emojis to use as topic icons
|
||||
* - :meth:`~telegram.Bot.hide_general_forum_topic`
|
||||
- Used to hide the general topic
|
||||
* - :meth:`~telegram.Bot.unhide_general_forum_topic`
|
||||
- Used to unhide the general topic
|
||||
* - :meth:`~telegram.Bot.reopen_forum_topic`
|
||||
- Used to reopen a topic
|
||||
* - :meth:`~telegram.Bot.reopen_general_forum_topic`
|
||||
- Used to reopen the general topic
|
||||
* - :meth:`~telegram.Bot.unpin_all_forum_topic_messages`
|
||||
- Used to unpin all messages in a forum topic
|
||||
* - :meth:`~telegram.Bot.unpin_all_general_forum_topic_messages`
|
||||
- Used to unpin all messages in the general forum topic
|
||||
|
||||
.. raw:: html
|
||||
|
||||
</details>
|
||||
<br>
|
||||
|
||||
.. raw:: html
|
||||
|
||||
<details>
|
||||
<summary>Payments and Stars</summary>
|
||||
|
||||
.. list-table::
|
||||
:align: left
|
||||
@@ -265,14 +390,39 @@
|
||||
|
||||
* - :meth:`~telegram.Bot.create_invoice_link`
|
||||
- Used to generate an HTTP link for an invoice
|
||||
* - :meth:`~telegram.Bot.edit_user_star_subscription`
|
||||
- Used for editing a user's star subscription
|
||||
* - :meth:`~telegram.Bot.get_star_transactions`
|
||||
- Used for obtaining the bot's Telegram Stars transactions
|
||||
* - :meth:`~telegram.Bot.refund_star_payment`
|
||||
- Used for refunding a payment in Telegram Stars
|
||||
|
||||
.. raw:: html
|
||||
|
||||
</details>
|
||||
<br>
|
||||
|
||||
.. raw:: html
|
||||
|
||||
<details>
|
||||
<summary>Miscellaneous</summary>
|
||||
|
||||
.. list-table::
|
||||
:align: left
|
||||
:widths: 1 4
|
||||
|
||||
* - :meth:`~telegram.Bot.close`
|
||||
- Used for closing server instance when switching to another local server
|
||||
* - :meth:`~telegram.Bot.log_out`
|
||||
- Used for logging out from cloud Bot API server
|
||||
* - :meth:`~telegram.Bot.get_file`
|
||||
- Used for getting basic info about a file
|
||||
* - :meth:`~telegram.Bot.get_available_gifts`
|
||||
- Used for getting information about gifts available for sending
|
||||
* - :meth:`~telegram.Bot.get_me`
|
||||
- Used for getting basic information about the bot
|
||||
* - :meth:`~telegram.Bot.save_prepared_inline_message`
|
||||
- Used for storing a message to be sent by a user of a Mini App
|
||||
|
||||
.. raw:: html
|
||||
|
||||
@@ -288,6 +438,10 @@
|
||||
:align: left
|
||||
:widths: 1 4
|
||||
|
||||
* - :attr:`~telegram.Bot.base_file_url`
|
||||
- Telegram Bot API file URL
|
||||
* - :attr:`~telegram.Bot.base_url`
|
||||
- Telegram Bot API service URL
|
||||
* - :attr:`~telegram.Bot.bot`
|
||||
- The user instance of the bot as returned by :meth:`~telegram.Bot.get_me`
|
||||
* - :attr:`~telegram.Bot.can_join_groups`
|
||||
@@ -302,12 +456,18 @@
|
||||
- The first name of the bot
|
||||
* - :attr:`~telegram.Bot.last_name`
|
||||
- The last name of the bot
|
||||
* - :attr:`~telegram.Bot.local_mode`
|
||||
- Whether the bot is running in local mode
|
||||
* - :attr:`~telegram.Bot.username`
|
||||
- The username of the bot, without leading ``@``
|
||||
* - :attr:`~telegram.Bot.link`
|
||||
- The t.me link of the bot
|
||||
* - :attr:`~telegram.Bot.private_key`
|
||||
- Deserialized private key for decryption of telegram passport data
|
||||
* - :attr:`~telegram.Bot.supports_inline_queries`
|
||||
- Whether the bot supports inline queries
|
||||
* - :attr:`~telegram.Bot.token`
|
||||
- Bot's unique authentication token
|
||||
|
||||
.. raw:: html
|
||||
|
||||
@@ -0,0 +1,3 @@
|
||||
.. raw:: html
|
||||
|
||||
<center><video height="300px" loop autoplay muted><source src="https://core.telegram.org/file/464001555/10fbd/jvTuV2Ke7WQ.1916669.mp4/a056de323645db409d" type="video/mp4"></video></center>
|
||||
@@ -0,0 +1,10 @@
|
||||
.. tip::
|
||||
When making requests to the Bot API in an asynchronous fashion (e.g. via
|
||||
:attr:`block=False <telegram.ext.BaseHandler.block>`, :meth:`Application.create_task <telegram.ext.Application.create_task>`,
|
||||
:meth:`~telegram.ext.ApplicationBuilder.concurrent_updates` or the :class:`~telegram.ext.JobQueue`), it can happen that more requests
|
||||
are being made in parallel than there are connections in the pool.
|
||||
If the number of requests is much higher than the number of connections, even setting
|
||||
:meth:`~telegram.ext.ApplicationBuilder.pool_timeout` to a larger value may not always be enough to prevent pool
|
||||
timeouts.
|
||||
You should therefore set :meth:`~telegram.ext.ApplicationBuilder.concurrent_updates`, :meth:`~telegram.ext.ApplicationBuilder.connection_pool_size` and
|
||||
:meth:`~telegram.ext.ApplicationBuilder.pool_timeout` to values that make sense for your setup.
|
||||
+16
-4
@@ -3,6 +3,18 @@
|
||||
You can adapt this file completely to your liking, but it should at least
|
||||
contain the root `toctree` directive.
|
||||
|
||||
.. raw:: html
|
||||
|
||||
<div style="display: none">
|
||||
|
||||
Hidden Headline
|
||||
===============
|
||||
This is just here to get furo to display the right sidebar.
|
||||
|
||||
.. raw:: html
|
||||
|
||||
</div>
|
||||
|
||||
.. include:: ../../README.rst
|
||||
|
||||
.. The toctrees are hidden such that they don't render on the start page but still include the contents into the documentation.
|
||||
@@ -27,12 +39,12 @@
|
||||
:hidden:
|
||||
:caption: Project
|
||||
|
||||
stability_policy
|
||||
changelog
|
||||
coc
|
||||
contributing
|
||||
testing
|
||||
Website <https://python-telegram-bot.org>
|
||||
GitHub Repository <https://github.com/python-telegram-bot/python-telegram-bot/>
|
||||
Telegram Channel <https://t.me/pythontelegrambotchannel/>
|
||||
Telegram User Group <https://t.me/pythontelegrambotgroup/>
|
||||
contributing
|
||||
coc
|
||||
|
||||
|
||||
|
||||
@@ -0,0 +1,148 @@
|
||||
.. _stability-policy:
|
||||
|
||||
Stability Policy
|
||||
================
|
||||
|
||||
.. important::
|
||||
|
||||
This stability policy is in place since version 20.3.
|
||||
While earlier versions of ``python-telegram-bot`` also had stable interfaces, they had no explicit stability policy and hence did not follow the rules outlined below in all detail.
|
||||
Please also refer to the :ref:`changelog <ptb-changelog>`.
|
||||
|
||||
.. caution::
|
||||
|
||||
Large parts of the :mod:`telegram` package are the Python representations of the Telegram Bot API, whose stability policy PTB can not influence.
|
||||
This policy hence includes some special cases for those parts.
|
||||
|
||||
What does this policy cover?
|
||||
----------------------------
|
||||
|
||||
This policy includes any API or behavior that is covered in this documentation.
|
||||
This covers both the :mod:`telegram` package and the :mod:`telegram.ext` package.
|
||||
|
||||
What doesn't this policy cover?
|
||||
-------------------------------
|
||||
|
||||
Introduction of new features or changes of flavors of comparable behavior (e.g. the default for the HTTP protocol version being used) are not covered by this policy.
|
||||
|
||||
The internal structure of classes in PTB, i.e. things like the result of ``dir(obj))`` or the contents of ``obj.__dict__``, is not covered by this policy.
|
||||
|
||||
Objects are in general not guaranteed to be pickleable (unless stated otherwise) and pickled objects from one version of PTB may not be loadable in future versions.
|
||||
We may provide a way to convert pickled objects from one version to another, but this is not guaranteed.
|
||||
|
||||
Functionality that is part of PTBs API but is explicitly documented as not being intended to be used directly by users (e.g. :meth:`telegram.request.BaseRequest.do_request`) may change.
|
||||
This also applies to functions or attributes marked as final in the sense of `PEP 591 <https://peps.python.org/pep-0591/>`__.
|
||||
|
||||
PTB has dependencies to third-party packages.
|
||||
The versions that PTB uses of these third-party packages may change if that does not affect PTBs public API.
|
||||
|
||||
PTB does not give guarantees about which Python versions are supported.
|
||||
In general, we will try to support all Python versions that have not yet reached their end of life, but we reserve ourselves the option to drop support for Python versions earlier if that benefits the advancement of the library.
|
||||
|
||||
PTB provides static type hints for all public attributes, parameters, return values and generic classes.
|
||||
These type hints are not covered by this policy and may change at any time under the condition that these changes have no impact on the runtime behavior of PTB.
|
||||
|
||||
.. _bot-api-functionality-1:
|
||||
|
||||
Bot API Functionality
|
||||
~~~~~~~~~~~~~~~~~~~~~
|
||||
|
||||
Comparison of equality of instances of the classes in the :mod:`telegram` package is subject to change and the PTB team will update the behavior to best reflect updates in the Bot API.
|
||||
Changes in this regard will be documented in the affected classes.
|
||||
Note that equality comparison with objects that where serialized by an older version of PTB may hence give unexpected results.
|
||||
|
||||
When the order of arguments of the Bot API methods changes or they become optional/mandatory due to changes in the Bot API, PTB will always try to reflect these changes.
|
||||
While we try to make such changes backward compatible, this is not always possible or only with significant effort.
|
||||
In such cases we will find a trade-off between backward compatibility and fully complying with the Bot API, which may result in breaking changes.
|
||||
We highly recommend using keyword arguments, which can help make such changes non-breaking on your end.
|
||||
|
||||
..
|
||||
We have documented a few common cases and possible backwards compatible solutions in the wiki as a reference for the dev team: https://github.com/python-telegram-bot/python-telegram-bot/wiki/Bot-API-Backward-Compatibility
|
||||
|
||||
When the Bot API changes attributes of classes, the method :meth:`telegram.TelegramObject.to_dict` will change as necessary to reflect these changes.
|
||||
In particular, attributes deprecated by Telegram will be removed from the returned dictionary.
|
||||
Deprecated attributes that are still passed by Telegram will be available in the :attr:`~telegram.TelegramObject.api_kwargs` dictionary as long as PTB can support that with feasible effort.
|
||||
Since attributes of the classes in the :mod:`telegram` package are not writable, we may change them to properties where appropriate.
|
||||
|
||||
Development Versions
|
||||
~~~~~~~~~~~~~~~~~~~~
|
||||
|
||||
Pre-releases marked as alpha, beta or release candidate are not covered by this policy.
|
||||
Before a feature is in a stable release, i.e. the feature was merged into the ``master`` branch but not released yet (or only in a pre-release), it is not covered by this policy either and may change.
|
||||
|
||||
Security
|
||||
~~~~~~~~
|
||||
|
||||
We make exceptions from our stability policy for security.
|
||||
We will violate this policy as necessary in order to resolve a security issue or harden PTB against a possible attack.
|
||||
|
||||
Versioning
|
||||
----------
|
||||
|
||||
PTB uses a versioning scheme that roughly follows `https://semver.org/ <https://semver.org/>`_, although it may not be quite as strict.
|
||||
|
||||
Given a version of PTB X.Y.Z,
|
||||
|
||||
- X indicates the major version number.
|
||||
This is incremented when backward incompatible changes are introduced.
|
||||
- Y indicates the minor version number.
|
||||
This is incremented when new functionality or backward compatible changes are introduced by PTB.
|
||||
*This is also incremented when PTB adds support for a new Bot API version, which may include backward incompatible changes in some cases as outlined* :ref:`below <bot-api-versioning>`.
|
||||
- Z is the patch version.
|
||||
This is incremented if backward compatible bug fixes or smaller changes are introduced.
|
||||
If this number is 0, it can be omitted, i.e. we just write X.Y instead of X.Y.0.
|
||||
|
||||
Deprecation
|
||||
~~~~~~~~~~~
|
||||
|
||||
From time to time we will want to change the behavior of an API or remove it entirely, or we do so to comply with changes in the Telegram Bot API.
|
||||
In those cases, we follow a deprecation schedule as detailed below.
|
||||
|
||||
Functionality is marked as deprecated by a corresponding note in the release notes and the documentation.
|
||||
Where possible, a :class:`~telegram.warnings.PTBDeprecationWarning` is issued when deprecated functionality is used, but this is not mandatory.
|
||||
|
||||
From time to time, we may decide to deprecate an API that is particularly widely used.
|
||||
In these cases, we may decide to provide an extended deprecation period, at our discretion.
|
||||
|
||||
With version 20.0.0, PTB introduced major structural breaking changes without the above deprecation period.
|
||||
Should a similarly big change ever be deemed necessary again by the development team and should a deprecation period prove too much additional effort, this violation of the stability policy will be announced well ahead of the release in our channel, `as was done for v20 <https://t.me/pythontelegrambotchannel/94>`_.
|
||||
|
||||
Non-Bot API Functionality
|
||||
#########################
|
||||
|
||||
Starting with version 20.3, deprecated functionality will stay available for the current and the next major version.
|
||||
For example:
|
||||
|
||||
- In PTB v20.1.1 the feature exists
|
||||
- In PTB v20.1.2 or v20.2.0 the feature is marked as deprecated
|
||||
- In PTB v21.*.* the feature is marked as deprecated
|
||||
- In PTB v22.0 the feature is removed or changed
|
||||
|
||||
.. _bot-api-versioning:
|
||||
|
||||
Bot API Functionality
|
||||
#####################
|
||||
|
||||
As PTB has no control over deprecations introduced by Telegram and the schedule of these deprecations rarely coincides with PTBs deprecation schedule, we have a special policy for Bot API functionality.
|
||||
|
||||
Starting with 20.3, deprecated Bot API functionality will stay available for the current and the next major version of PTB *or* until the next version of the Bot API.
|
||||
More precisely, two cases are possible, for which we show examples below.
|
||||
|
||||
Case 1
|
||||
^^^^^^
|
||||
|
||||
- In PTB v20.1 the feature exists
|
||||
- Bot API version 6.6 is released and deprecates the feature
|
||||
- PTB v20.2 adds support for Bot API 6.6 and the feature is
|
||||
marked as deprecated
|
||||
- In PTB v21.0 the feature is removed or changed
|
||||
|
||||
Case 2
|
||||
^^^^^^
|
||||
|
||||
- In PTB v20.1 the feature exists
|
||||
- Bot API version 6.6 is released and deprecates the feature
|
||||
- PTB v20.2 adds support for Bot API version 6.6 and the feature is marked as deprecated
|
||||
- In PTB v20.2.* and v20.3.* the feature is marked as deprecated
|
||||
- Bot API version 6.7 is released
|
||||
- PTB v20.4 adds support for Bot API version 6.7 and the feature is removed or changed
|
||||
@@ -0,0 +1,6 @@
|
||||
AffiliateInfo
|
||||
=============
|
||||
|
||||
.. autoclass:: telegram.AffiliateInfo
|
||||
:members:
|
||||
:show-inheritance:
|
||||
@@ -1,5 +1,5 @@
|
||||
telegram.Animation
|
||||
==================
|
||||
Animation
|
||||
=========
|
||||
|
||||
.. Also lists methods of _BaseThumbedMedium, but not the ones of TelegramObject
|
||||
|
||||
|
||||
@@ -0,0 +1,161 @@
|
||||
Available Types
|
||||
---------------
|
||||
|
||||
.. toctree::
|
||||
:titlesonly:
|
||||
|
||||
telegram.animation
|
||||
telegram.audio
|
||||
telegram.birthdate
|
||||
telegram.botcommand
|
||||
telegram.botcommandscope
|
||||
telegram.botcommandscopeallchatadministrators
|
||||
telegram.botcommandscopeallgroupchats
|
||||
telegram.botcommandscopeallprivatechats
|
||||
telegram.botcommandscopechat
|
||||
telegram.botcommandscopechatadministrators
|
||||
telegram.botcommandscopechatmember
|
||||
telegram.botcommandscopedefault
|
||||
telegram.botdescription
|
||||
telegram.botname
|
||||
telegram.botshortdescription
|
||||
telegram.businessconnection
|
||||
telegram.businessintro
|
||||
telegram.businesslocation
|
||||
telegram.businessopeninghours
|
||||
telegram.businessopeninghoursinterval
|
||||
telegram.businessmessagesdeleted
|
||||
telegram.callbackquery
|
||||
telegram.chat
|
||||
telegram.chatadministratorrights
|
||||
telegram.chatbackground
|
||||
telegram.copytextbutton
|
||||
telegram.backgroundtype
|
||||
telegram.backgroundtypefill
|
||||
telegram.backgroundtypewallpaper
|
||||
telegram.backgroundtypepattern
|
||||
telegram.backgroundtypechattheme
|
||||
telegram.backgroundfill
|
||||
telegram.backgroundfillsolid
|
||||
telegram.backgroundfillgradient
|
||||
telegram.backgroundfillfreeformgradient
|
||||
telegram.chatboost
|
||||
telegram.chatboostadded
|
||||
telegram.chatboostremoved
|
||||
telegram.chatboostsource
|
||||
telegram.chatboostsourcegiftcode
|
||||
telegram.chatboostsourcegiveaway
|
||||
telegram.chatboostsourcepremium
|
||||
telegram.chatboostupdated
|
||||
telegram.chatfullinfo
|
||||
telegram.chatinvitelink
|
||||
telegram.chatjoinrequest
|
||||
telegram.chatlocation
|
||||
telegram.chatmember
|
||||
telegram.chatmemberadministrator
|
||||
telegram.chatmemberbanned
|
||||
telegram.chatmemberleft
|
||||
telegram.chatmembermember
|
||||
telegram.chatmemberowner
|
||||
telegram.chatmemberrestricted
|
||||
telegram.chatmemberupdated
|
||||
telegram.chatpermissions
|
||||
telegram.chatphoto
|
||||
telegram.chatshared
|
||||
telegram.contact
|
||||
telegram.dice
|
||||
telegram.document
|
||||
telegram.externalreplyinfo
|
||||
telegram.file
|
||||
telegram.forcereply
|
||||
telegram.forumtopic
|
||||
telegram.forumtopicclosed
|
||||
telegram.forumtopiccreated
|
||||
telegram.forumtopicedited
|
||||
telegram.forumtopicreopened
|
||||
telegram.generalforumtopichidden
|
||||
telegram.generalforumtopicunhidden
|
||||
telegram.giveaway
|
||||
telegram.giveawaycompleted
|
||||
telegram.giveawaycreated
|
||||
telegram.giveawaywinners
|
||||
telegram.inaccessiblemessage
|
||||
telegram.inlinekeyboardbutton
|
||||
telegram.inlinekeyboardmarkup
|
||||
telegram.inputfile
|
||||
telegram.inputmedia
|
||||
telegram.inputmediaanimation
|
||||
telegram.inputmediaaudio
|
||||
telegram.inputmediadocument
|
||||
telegram.inputmediaphoto
|
||||
telegram.inputmediavideo
|
||||
telegram.inputpaidmedia
|
||||
telegram.inputpaidmediaphoto
|
||||
telegram.inputpaidmediavideo
|
||||
telegram.inputpolloption
|
||||
telegram.keyboardbutton
|
||||
telegram.keyboardbuttonpolltype
|
||||
telegram.keyboardbuttonrequestchat
|
||||
telegram.keyboardbuttonrequestusers
|
||||
telegram.linkpreviewoptions
|
||||
telegram.location
|
||||
telegram.loginurl
|
||||
telegram.maybeinaccessiblemessage
|
||||
telegram.menubutton
|
||||
telegram.menubuttoncommands
|
||||
telegram.menubuttondefault
|
||||
telegram.menubuttonwebapp
|
||||
telegram.message
|
||||
telegram.messageautodeletetimerchanged
|
||||
telegram.messageentity
|
||||
telegram.messageid
|
||||
telegram.messageorigin
|
||||
telegram.messageoriginchannel
|
||||
telegram.messageoriginchat
|
||||
telegram.messageoriginhiddenuser
|
||||
telegram.messageoriginuser
|
||||
telegram.messagereactioncountupdated
|
||||
telegram.messagereactionupdated
|
||||
telegram.paidmedia
|
||||
telegram.paidmediainfo
|
||||
telegram.paidmediaphoto
|
||||
telegram.paidmediapreview
|
||||
telegram.paidmediapurchased
|
||||
telegram.paidmediavideo
|
||||
telegram.photosize
|
||||
telegram.poll
|
||||
telegram.pollanswer
|
||||
telegram.polloption
|
||||
telegram.proximityalerttriggered
|
||||
telegram.reactioncount
|
||||
telegram.reactiontype
|
||||
telegram.reactiontypecustomemoji
|
||||
telegram.reactiontypeemoji
|
||||
telegram.reactiontypepaid
|
||||
telegram.replykeyboardmarkup
|
||||
telegram.replykeyboardremove
|
||||
telegram.replyparameters
|
||||
telegram.sentwebappmessage
|
||||
telegram.shareduser
|
||||
telegram.story
|
||||
telegram.switchinlinequerychosenchat
|
||||
telegram.telegramobject
|
||||
telegram.textquote
|
||||
telegram.update
|
||||
telegram.user
|
||||
telegram.userchatboosts
|
||||
telegram.userprofilephotos
|
||||
telegram.usersshared
|
||||
telegram.venue
|
||||
telegram.video
|
||||
telegram.videochatended
|
||||
telegram.videochatparticipantsinvited
|
||||
telegram.videochatscheduled
|
||||
telegram.videochatstarted
|
||||
telegram.videonote
|
||||
telegram.voice
|
||||
telegram.webappdata
|
||||
telegram.webappinfo
|
||||
telegram.webhookinfo
|
||||
telegram.writeaccessallowed
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
telegram.Audio
|
||||
==============
|
||||
Audio
|
||||
=====
|
||||
|
||||
.. Also lists methods of _BaseThumbedMedium, but not the ones of TelegramObject
|
||||
|
||||
|
||||
@@ -0,0 +1,8 @@
|
||||
BackgroundFill
|
||||
==============
|
||||
|
||||
.. versionadded:: 21.2
|
||||
|
||||
.. autoclass:: telegram.BackgroundFill
|
||||
:members:
|
||||
:show-inheritance:
|
||||
@@ -0,0 +1,8 @@
|
||||
BackgroundFillFreeformGradient
|
||||
==============================
|
||||
|
||||
.. versionadded:: 21.2
|
||||
|
||||
.. autoclass:: telegram.BackgroundFillFreeformGradient
|
||||
:members:
|
||||
:show-inheritance:
|
||||
@@ -0,0 +1,8 @@
|
||||
BackgroundFillGradient
|
||||
======================
|
||||
|
||||
.. versionadded:: 21.2
|
||||
|
||||
.. autoclass:: telegram.BackgroundFillGradient
|
||||
:members:
|
||||
:show-inheritance:
|
||||
@@ -0,0 +1,8 @@
|
||||
BackgroundFillSolid
|
||||
===================
|
||||
|
||||
.. versionadded:: 21.2
|
||||
|
||||
.. autoclass:: telegram.BackgroundFillSolid
|
||||
:members:
|
||||
:show-inheritance:
|
||||
@@ -0,0 +1,8 @@
|
||||
BackgroundType
|
||||
==============
|
||||
|
||||
.. versionadded:: 21.2
|
||||
|
||||
.. autoclass:: telegram.BackgroundType
|
||||
:members:
|
||||
:show-inheritance:
|
||||
@@ -0,0 +1,8 @@
|
||||
BackgroundTypeChatTheme
|
||||
=======================
|
||||
|
||||
.. versionadded:: 21.2
|
||||
|
||||
.. autoclass:: telegram.BackgroundTypeChatTheme
|
||||
:members:
|
||||
:show-inheritance:
|
||||
@@ -0,0 +1,8 @@
|
||||
BackgroundTypeFill
|
||||
==================
|
||||
|
||||
.. versionadded:: 21.2
|
||||
|
||||
.. autoclass:: telegram.BackgroundTypeFill
|
||||
:members:
|
||||
:show-inheritance:
|
||||
@@ -0,0 +1,8 @@
|
||||
BackgroundTypePattern
|
||||
=====================
|
||||
|
||||
.. versionadded:: 21.2
|
||||
|
||||
.. autoclass:: telegram.BackgroundTypePattern
|
||||
:members:
|
||||
:show-inheritance:
|
||||
@@ -0,0 +1,8 @@
|
||||
BackgroundTypeWallpaper
|
||||
=======================
|
||||
|
||||
.. versionadded:: 21.2
|
||||
|
||||
.. autoclass:: telegram.BackgroundTypeWallpaper
|
||||
:members:
|
||||
:show-inheritance:
|
||||
@@ -0,0 +1,7 @@
|
||||
Birthdate
|
||||
=========
|
||||
|
||||
.. autoclass:: telegram.Birthdate
|
||||
:members:
|
||||
:show-inheritance:
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
telegram.Bot
|
||||
============
|
||||
Bot
|
||||
===
|
||||
|
||||
.. autoclass:: telegram.Bot
|
||||
:members:
|
||||
:show-inheritance:
|
||||
:show-inheritance:
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
telegram.BotCommand
|
||||
===================
|
||||
BotCommand
|
||||
==========
|
||||
|
||||
.. autoclass:: telegram.BotCommand
|
||||
:members:
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
telegram.BotCommandScope
|
||||
========================
|
||||
BotCommandScope
|
||||
===============
|
||||
|
||||
.. autoclass:: telegram.BotCommandScope
|
||||
:members:
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
telegram.BotCommandScopeAllChatAdministrators
|
||||
=============================================
|
||||
BotCommandScopeAllChatAdministrators
|
||||
====================================
|
||||
|
||||
.. autoclass:: telegram.BotCommandScopeAllChatAdministrators
|
||||
:members:
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
telegram.BotCommandScopeAllGroupChats
|
||||
=======================================
|
||||
BotCommandScopeAllGroupChats
|
||||
============================
|
||||
|
||||
.. autoclass:: telegram.BotCommandScopeAllGroupChats
|
||||
:members:
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
telegram.BotCommandScopeAllPrivateChats
|
||||
=======================================
|
||||
BotCommandScopeAllPrivateChats
|
||||
==============================
|
||||
|
||||
.. autoclass:: telegram.BotCommandScopeAllPrivateChats
|
||||
:members:
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
telegram.BotCommandScopeChat
|
||||
============================
|
||||
BotCommandScopeChat
|
||||
===================
|
||||
|
||||
.. autoclass:: telegram.BotCommandScopeChat
|
||||
:members:
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
telegram.BotCommandScopeChatAdministrators
|
||||
==========================================
|
||||
BotCommandScopeChatAdministrators
|
||||
=================================
|
||||
|
||||
.. autoclass:: telegram.BotCommandScopeChatAdministrators
|
||||
:members:
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
telegram.BotCommandScopeChatMember
|
||||
==================================
|
||||
BotCommandScopeChatMember
|
||||
=========================
|
||||
|
||||
.. autoclass:: telegram.BotCommandScopeChatMember
|
||||
:members:
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
telegram.BotCommandScopeDefault
|
||||
===============================
|
||||
BotCommandScopeDefault
|
||||
======================
|
||||
|
||||
.. autoclass:: telegram.BotCommandScopeDefault
|
||||
:members:
|
||||
|
||||
@@ -0,0 +1,6 @@
|
||||
BotDescription
|
||||
==============
|
||||
|
||||
.. autoclass:: telegram.BotDescription
|
||||
:members:
|
||||
:show-inheritance:
|
||||
@@ -0,0 +1,6 @@
|
||||
BotName
|
||||
=======
|
||||
|
||||
.. autoclass:: telegram.BotName
|
||||
:members:
|
||||
:show-inheritance:
|
||||
@@ -0,0 +1,6 @@
|
||||
BotShortDescription
|
||||
===================
|
||||
|
||||
.. autoclass:: telegram.BotShortDescription
|
||||
:members:
|
||||
:show-inheritance:
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user