mirror of
https://github.com/aiogram/aiogram.git
synced 2026-04-08 16:37:47 +00:00
Merge branch 'dev-3.x' into dev-3.x-flat-package
# Conflicts: # tests/test_filters/test_state.py
This commit is contained in:
commit
01e5b3e456
10 changed files with 133 additions and 11 deletions
33
.github/workflows/pull_request_changelog.yml
vendored
33
.github/workflows/pull_request_changelog.yml
vendored
|
|
@ -1,3 +1,4 @@
|
|||
name: "Check that changes are described"
|
||||
on:
|
||||
pull_request_target:
|
||||
types:
|
||||
|
|
@ -8,31 +9,32 @@ on:
|
|||
- "unlabeled"
|
||||
|
||||
jobs:
|
||||
check_changes:
|
||||
changes-required:
|
||||
runs-on: ubuntu-latest
|
||||
name: "Check that changes is described"
|
||||
if: "!contains(github.event.pull_request.labels.*.name, 'skip news')"
|
||||
steps:
|
||||
- name: "Checkout code"
|
||||
- name: Checkout code
|
||||
uses: actions/checkout@master
|
||||
with:
|
||||
ref: ${{ github.event.pull_request.head.sha }}
|
||||
fetch-depth: '0'
|
||||
|
||||
- name: Set up Python 3.10
|
||||
uses: actions/setup-python@v2
|
||||
with:
|
||||
python-version: "3.10"
|
||||
|
||||
- name: Install towncrier
|
||||
run: pip install towncrier
|
||||
|
||||
- name: "Check changelog"
|
||||
if: "!contains(github.event.pull_request.labels.*.name, 'skip news')"
|
||||
- name: Check changelog
|
||||
env:
|
||||
BASE_BRANCH: ${{ github.base_ref }}
|
||||
run: |
|
||||
git fetch --no-tags origin +refs/heads/${BASE_BRANCH}:refs/remotes/origin/${BASE_BRANCH}
|
||||
towncrier check --compare-with origin/${BASE_BRANCH}
|
||||
|
||||
- name: Find Comment
|
||||
- name: Find bot comment
|
||||
if: "always()"
|
||||
uses: peter-evans/find-comment@v2
|
||||
id: fc
|
||||
|
|
@ -41,7 +43,7 @@ jobs:
|
|||
comment-author: 'github-actions[bot]'
|
||||
body-includes: Changelog
|
||||
|
||||
- name: Create fail comment
|
||||
- name: Ask for changelog
|
||||
if: "failure()"
|
||||
uses: peter-evans/create-or-update-comment@v2
|
||||
with:
|
||||
|
|
@ -57,7 +59,7 @@ jobs:
|
|||
|
||||
Read more at [Towncrier docs](https://towncrier.readthedocs.io/en/latest/quickstart.html#creating-news-fragments)
|
||||
|
||||
- name: Create success comment
|
||||
- name: Changelog found
|
||||
if: "success()"
|
||||
uses: peter-evans/create-or-update-comment@v2
|
||||
with:
|
||||
|
|
@ -69,8 +71,19 @@ jobs:
|
|||
|
||||
Thank you for adding a description of the changes
|
||||
|
||||
skip-news:
|
||||
runs-on: ubuntu-latest
|
||||
if: "contains(github.event.pull_request.labels.*.name, 'skip news')"
|
||||
steps:
|
||||
- name: Find bot comment
|
||||
uses: peter-evans/find-comment@v2
|
||||
id: fc
|
||||
with:
|
||||
issue-number: ${{ github.event.pull_request.number }}
|
||||
comment-author: 'github-actions[bot]'
|
||||
body-includes: Changelog
|
||||
|
||||
- name: Comment when docs is not needed
|
||||
if: "contains(github.event.pull_request.labels.*.name, 'skip news')"
|
||||
uses: peter-evans/create-or-update-comment@v2
|
||||
with:
|
||||
edit-mode: replace
|
||||
|
|
@ -79,4 +92,4 @@ jobs:
|
|||
body: |
|
||||
# :corn: Changelog is not needed.
|
||||
|
||||
This PR does not require a changelog in due to the `skip news` label.
|
||||
This PR does not require a changelog because `skip news` label is present.
|
||||
|
|
|
|||
22
.github/workflows/tests.yml
vendored
22
.github/workflows/tests.yml
vendored
|
|
@ -4,9 +4,29 @@ on:
|
|||
push:
|
||||
branches:
|
||||
- dev-3.x
|
||||
paths:
|
||||
- ".github/workflows/tests.yml"
|
||||
- "aiogram/**"
|
||||
- "tests/**"
|
||||
- ".coveragerc"
|
||||
- ".flake8"
|
||||
- "codecov.yaml"
|
||||
- "mypy.ini"
|
||||
- "poetry.lock"
|
||||
- "pyproject.toml"
|
||||
pull_request:
|
||||
branches:
|
||||
- dev-3.x
|
||||
paths:
|
||||
- ".github/workflows/tests.yml"
|
||||
- "aiogram/**"
|
||||
- "tests/**"
|
||||
- ".coveragerc"
|
||||
- ".flake8"
|
||||
- "codecov.yaml"
|
||||
- "mypy.ini"
|
||||
- "poetry.lock"
|
||||
- "pyproject.toml"
|
||||
|
||||
jobs:
|
||||
build:
|
||||
|
|
@ -24,7 +44,7 @@ jobs:
|
|||
- '3.10'
|
||||
|
||||
defaults:
|
||||
# Windows is sucks. Force use bash instead of PowerShell
|
||||
# Windows sucks. Force use bash instead of PowerShell
|
||||
run:
|
||||
shell: bash
|
||||
|
||||
|
|
|
|||
3
CHANGES/803.feature
Normal file
3
CHANGES/803.feature
Normal file
|
|
@ -0,0 +1,3 @@
|
|||
Add class helper ChatAction for constants that Telegram BotAPI uses in sendChatAction request.
|
||||
In my opinion, this will help users and will also improve compatibility with 2.x version
|
||||
where similar class was called "ChatActions".
|
||||
1
CHANGES/927.bugfix.rst
Normal file
1
CHANGES/927.bugfix.rst
Normal file
|
|
@ -0,0 +1 @@
|
|||
Fixed the ability to compare the state, now comparison to copy of the state will return `True`.
|
||||
|
|
@ -54,6 +54,16 @@ class State:
|
|||
return True
|
||||
return raw_state == self.state
|
||||
|
||||
def __eq__(self, other: Any) -> bool:
|
||||
if isinstance(other, self.__class__):
|
||||
return self.state == other.state
|
||||
if isinstance(other, str):
|
||||
return self.state == other
|
||||
return NotImplemented
|
||||
|
||||
def __hash__(self) -> int:
|
||||
return hash(self.state)
|
||||
|
||||
|
||||
class StatesGroupMeta(type):
|
||||
__parent__: "Optional[Type[StatesGroup]]"
|
||||
|
|
|
|||
|
|
@ -13,6 +13,7 @@ from .bot_command_scope_default import BotCommandScopeDefault
|
|||
from .callback_game import CallbackGame
|
||||
from .callback_query import CallbackQuery
|
||||
from .chat import Chat
|
||||
from .chat_action import ChatAction
|
||||
from .chat_administrator_rights import ChatAdministratorRights
|
||||
from .chat_invite_link import ChatInviteLink
|
||||
from .chat_join_request import ChatJoinRequest
|
||||
|
|
@ -275,6 +276,7 @@ __all__ = (
|
|||
"Game",
|
||||
"CallbackGame",
|
||||
"GameHighScore",
|
||||
"ChatAction",
|
||||
)
|
||||
|
||||
# Load typing forward refs for every TelegramObject
|
||||
|
|
|
|||
33
aiogram/types/chat_action.py
Normal file
33
aiogram/types/chat_action.py
Normal file
|
|
@ -0,0 +1,33 @@
|
|||
import enum
|
||||
|
||||
from ..utils.enum import AutoName
|
||||
|
||||
|
||||
class ChatAction(AutoName):
|
||||
"""
|
||||
This object represents bot actions.
|
||||
|
||||
Choose one, depending on what the user is about to receive:
|
||||
• typing for text messages,
|
||||
• upload_photo for photos,
|
||||
• record_video or upload_video for videos,
|
||||
• record_voice or upload_voice for voice notes,
|
||||
• upload_document for general files,
|
||||
• choose_sticker for stickers,
|
||||
• find_location for location data,
|
||||
• record_video_note or upload_video_note for video notes.
|
||||
|
||||
Source: https://core.telegram.org/bots/api#sendchataction
|
||||
"""
|
||||
|
||||
TYPING = enum.auto()
|
||||
UPLOAD_PHOTO = enum.auto()
|
||||
RECORD_VIDEO = enum.auto()
|
||||
UPLOAD_VIDEO = enum.auto()
|
||||
RECORD_VOICE = enum.auto()
|
||||
UPLOAD_VOICE = enum.auto()
|
||||
UPLOAD_DOCUMENT = enum.auto()
|
||||
CHOOSE_STICKER = enum.auto()
|
||||
FIND_LOCATION = enum.auto()
|
||||
RECORD_VIDEO_NOTE = enum.auto()
|
||||
UPLOAD_VIDEO_NOTE = enum.auto()
|
||||
8
aiogram/utils/enum.py
Normal file
8
aiogram/utils/enum.py
Normal file
|
|
@ -0,0 +1,8 @@
|
|||
import enum
|
||||
from typing import Any, List
|
||||
|
||||
|
||||
class AutoName(str, enum.Enum):
|
||||
@staticmethod
|
||||
def _generate_next_value_(name: str, start: int, count: int, last_values: List[Any]) -> str:
|
||||
return name.lower()
|
||||
|
|
@ -1,6 +1,7 @@
|
|||
import pytest
|
||||
|
||||
from aiogram.methods import Request, SendChatAction
|
||||
from aiogram.types import ChatAction
|
||||
from tests.mocked_bot import MockedBot
|
||||
|
||||
pytestmark = pytest.mark.asyncio
|
||||
|
|
@ -22,3 +23,12 @@ class TestSendChatAction:
|
|||
request: Request = bot.get_request()
|
||||
assert request.method == "sendChatAction"
|
||||
assert response == prepare_result.result
|
||||
|
||||
async def test_chat_action_class(self, bot: MockedBot):
|
||||
prepare_result = bot.add_result_for(SendChatAction, ok=True, result=True)
|
||||
|
||||
response: bool = await bot.send_chat_action(chat_id=42, action=ChatAction.TYPING)
|
||||
request: Request = bot.get_request()
|
||||
assert request.method == "sendChatAction"
|
||||
assert request.data["action"] == "typing"
|
||||
assert response == prepare_result.result
|
||||
|
|
|
|||
|
|
@ -1,7 +1,9 @@
|
|||
from copy import copy
|
||||
from inspect import isclass
|
||||
|
||||
import pytest
|
||||
|
||||
from aiogram.dispatcher.event.handler import FilterObject
|
||||
from aiogram.filters import StateFilter
|
||||
from aiogram.fsm.state import State, StatesGroup
|
||||
from aiogram.types import Update
|
||||
|
|
@ -50,3 +52,23 @@ class TestStateFilter:
|
|||
async def test_filter(self, state, current_state, result):
|
||||
f = StateFilter(state=state)
|
||||
assert bool(await f(obj=Update(update_id=42), raw_state=current_state)) is result
|
||||
|
||||
@pytestmark
|
||||
async def test_create_filter_from_state(self):
|
||||
FilterObject(callback=State(state="state"))
|
||||
|
||||
@pytestmark
|
||||
async def test_state_copy(self):
|
||||
class SG(StatesGroup):
|
||||
state = State()
|
||||
|
||||
assert SG.state == copy(SG.state)
|
||||
|
||||
assert SG.state == "SG:state"
|
||||
assert "SG:state" == SG.state
|
||||
|
||||
assert State() == State()
|
||||
assert SG.state != 1
|
||||
|
||||
states = {SG.state: "OK"}
|
||||
assert states.get(copy(SG.state)) == "OK"
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue