add ruff format, ruff check, time_picker, project structure and imports reorganized

This commit is contained in:
Alexander Kalinovsky
2025-01-21 23:50:19 +01:00
parent ced47ac993
commit 9dd0708a5b
58 changed files with 3690 additions and 2583 deletions

View File

@@ -1,20 +1,85 @@
from typing import Any, Callable, TYPE_CHECKING
from aiogram.types import Message, CallbackQuery
from aiogram.fsm.context import FSMContext
from aiogram.utils.i18n import I18n
from aiogram.utils.keyboard import InlineKeyboardBuilder
from typing import Any, Callable, TYPE_CHECKING, Literal
from babel.support import LazyProxy
from dataclasses import dataclass, field
from sqlmodel.ext.asyncio.session import AsyncSession
from .role import RoleBase
from . import EntityPermission
from ..bot.handlers.context import ContextData
if TYPE_CHECKING:
from .bot_entity import BotEntity
from ..main import QBotApp
from .user import UserBase
EntityCaptionCallable = Callable[["EntityDescriptor"], str]
EntityItemCaptionCallable = Callable[["EntityDescriptor", Any], str]
EntityFieldCaptionCallable = Callable[["EntityFieldDescriptor", Any, Any], str]
@dataclass(kw_only = True)
class _BaseEntityFieldDescriptor():
@dataclass
class FieldEditButton:
field_name: str
caption: str | LazyProxy | EntityFieldCaptionCallable | None = None
@dataclass
class CommandButton:
command: str
caption: str | LazyProxy | EntityItemCaptionCallable | None = None
context_data: ContextData | None = None
@dataclass
class Filter:
field_name: str
operator: Literal[
"==",
"!=",
">",
"<",
">=",
"<=",
"in",
"not in",
"like",
"ilike",
"is",
"is not",
]
value_type: Literal["const", "param"]
value: Any | None = None
param_index: int | None = None
@dataclass
class EntityList:
caption: str | LazyProxy | EntityCaptionCallable | None = None
item_repr: EntityItemCaptionCallable | None = None
show_add_new_button: bool = True
item_form: str | None = None
pagination: bool = True
static_filters: list[Filter] | Any = None
filtering: bool = True
filtering_fields: list[str] = None
order_by: str | Any | None = None
@dataclass
class EntityForm:
item_repr: EntityItemCaptionCallable | None = None
edit_field_sequence: list[str] = None
form_buttons: list[list[FieldEditButton | CommandButton]] = None
show_edit_button: bool = True
show_delete_button: bool = True
@dataclass(kw_only=True)
class _BaseEntityFieldDescriptor:
icon: str = None
caption: str | LazyProxy | EntityFieldCaptionCallable | None = None
description: str | LazyProxy | EntityFieldCaptionCallable | None = None
@@ -24,21 +89,25 @@ class _BaseEntityFieldDescriptor():
localizable: bool = False
bool_false_value: str | LazyProxy = "no"
bool_true_value: str | LazyProxy = "yes"
ep_form: str | None = None
ep_parent_field: str | None = None
ep_child_field: str | None = None
dt_type: Literal["date", "datetime"] = "date"
default: Any = None
@dataclass(kw_only = True)
@dataclass(kw_only=True)
class EntityField(_BaseEntityFieldDescriptor):
name: str | None = None
sm_descriptor: Any = None
@dataclass(kw_only = True)
@dataclass(kw_only=True)
class Setting(_BaseEntityFieldDescriptor):
name: str | None = None
@dataclass(kw_only = True)
@dataclass(kw_only=True)
class EntityFieldDescriptor(_BaseEntityFieldDescriptor):
name: str
field_name: str
@@ -52,42 +121,80 @@ class EntityFieldDescriptor(_BaseEntityFieldDescriptor):
return self.name.__hash__()
@dataclass(kw_only = True)
@dataclass(kw_only=True)
class _BaseEntityDescriptor:
icon: str = "📘"
caption: str | LazyProxy | EntityCaptionCallable | None = None
caption_plural: str | LazyProxy | EntityCaptionCallable | None = None
full_name: str | LazyProxy | EntityCaptionCallable | None = None
full_name_plural: str | LazyProxy | EntityCaptionCallable | None = None
description: str | LazyProxy | EntityCaptionCallable | None = None
item_caption: EntityItemCaptionCallable | None = None
item_repr: EntityItemCaptionCallable | None = None
default_list: EntityList = field(default_factory=EntityList)
default_form: EntityForm = field(default_factory=EntityForm)
lists: dict[str, EntityList] = field(default_factory=dict[str, EntityList])
forms: dict[str, EntityForm] = field(default_factory=dict[str, EntityForm])
show_in_entities_menu: bool = True
field_sequence: list[str] = None
edit_button_visible: bool = True
edit_buttons: list[list[str | tuple[str, str | LazyProxy | EntityFieldCaptionCallable]]] = None
permissions: dict[EntityPermission, list[RoleBase]] = field(default_factory = lambda: {
EntityPermission.LIST: [RoleBase.DEFAULT_USER, RoleBase.SUPER_USER],
EntityPermission.READ: [RoleBase.DEFAULT_USER, RoleBase.SUPER_USER],
EntityPermission.CREATE: [RoleBase.DEFAULT_USER, RoleBase.SUPER_USER],
EntityPermission.UPDATE: [RoleBase.DEFAULT_USER, RoleBase.SUPER_USER],
EntityPermission.DELETE: [RoleBase.DEFAULT_USER, RoleBase.SUPER_USER],
EntityPermission.LIST_ALL: [RoleBase.SUPER_USER],
EntityPermission.READ_ALL: [RoleBase.SUPER_USER],
EntityPermission.CREATE_ALL: [RoleBase.SUPER_USER],
EntityPermission.UPDATE_ALL: [RoleBase.SUPER_USER],
EntityPermission.DELETE_ALL: [RoleBase.SUPER_USER]
})
ownership_fields: dict[RoleBase, str] = field(default_factory=dict[RoleBase, str])
permissions: dict[EntityPermission, list[RoleBase]] = field(
default_factory=lambda: {
EntityPermission.LIST: [RoleBase.DEFAULT_USER, RoleBase.SUPER_USER],
EntityPermission.READ: [RoleBase.DEFAULT_USER, RoleBase.SUPER_USER],
EntityPermission.CREATE: [RoleBase.DEFAULT_USER, RoleBase.SUPER_USER],
EntityPermission.UPDATE: [RoleBase.DEFAULT_USER, RoleBase.SUPER_USER],
EntityPermission.DELETE: [RoleBase.DEFAULT_USER, RoleBase.SUPER_USER],
EntityPermission.LIST_ALL: [RoleBase.SUPER_USER],
EntityPermission.READ_ALL: [RoleBase.SUPER_USER],
EntityPermission.CREATE_ALL: [RoleBase.SUPER_USER],
EntityPermission.UPDATE_ALL: [RoleBase.SUPER_USER],
EntityPermission.DELETE_ALL: [RoleBase.SUPER_USER],
}
)
@dataclass(kw_only = True)
@dataclass(kw_only=True)
class Entity(_BaseEntityDescriptor):
name: str | None = None
@dataclass
class EntityDescriptor(_BaseEntityDescriptor):
name: str
class_name: str
type_: type["BotEntity"]
fields_descriptors: dict[str, EntityFieldDescriptor]
@dataclass(kw_only=True)
class CommandCallbackContext[UT: UserBase]:
keyboard_builder: InlineKeyboardBuilder = field(
default_factory=InlineKeyboardBuilder
)
message_text: str | None = None
register_navigation: bool = True
message: Message | CallbackQuery
callback_data: ContextData
db_session: AsyncSession
user: UT
app: "QBotApp"
state_data: dict[str, Any]
state: FSMContext
i18n: I18n
kwargs: dict[str, Any] = field(default_factory=dict)
@dataclass(kw_only=True)
class _BotCommand:
name: str
caption: str | dict[str, str] | None = None
show_in_bot_commands: bool = False
register_navigation: bool = True
clear_navigation: bool = False
clear_state: bool = True
@dataclass(kw_only=True)
class BotCommand(_BotCommand):
handler: Callable[[CommandCallbackContext], None]
@dataclass(kw_only=True)
class Command(_BotCommand): ...