Merge branch 'master' into 2023.4
# Conflicts: # src/cpl_cli/.cpl/__init__.py # src/cpl_cli/__init__.py # src/cpl_cli/_templates/__init__.py # src/cpl_cli/_templates/build/__init__.py # src/cpl_cli/_templates/publish/__init__.py # src/cpl_cli/abc/__init__.py # src/cpl_cli/command/__init__.py # src/cpl_cli/configuration/__init__.py # src/cpl_cli/cpl-cli.json # src/cpl_cli/helper/__init__.py # src/cpl_cli/live_server/__init__.py # src/cpl_cli/migrations/__init__.py # src/cpl_cli/migrations/base/__init__.py # src/cpl_cli/migrations/service/__init__.py # src/cpl_cli/publish/__init__.py # src/cpl_cli/source_creator/__init__.py # src/cpl_cli/validators/__init__.py # src/cpl_core/__init__.py # src/cpl_core/application/__init__.py # src/cpl_core/configuration/__init__.py # src/cpl_core/console/__init__.py # src/cpl_core/cpl-core.json # src/cpl_core/database/__init__.py # src/cpl_core/database/connection/__init__.py # src/cpl_core/database/context/__init__.py # src/cpl_core/dependency_injection/__init__.py # src/cpl_core/dependency_injection/service_provider.py # src/cpl_core/dependency_injection/service_provider_abc.py # src/cpl_core/environment/__init__.py # src/cpl_core/logging/__init__.py # src/cpl_core/mailing/__init__.py # src/cpl_core/pipes/__init__.py # src/cpl_core/time/__init__.py # src/cpl_core/utils/__init__.py # src/cpl_discord/.cpl/__init__.py # src/cpl_discord/.cpl/schematic_discord_event.py # src/cpl_discord/__init__.py # src/cpl_discord/application/__init__.py # src/cpl_discord/command/__init__.py # src/cpl_discord/configuration/__init__.py # src/cpl_discord/container/__init__.py # src/cpl_discord/cpl-discord.json # src/cpl_discord/events/__init__.py # src/cpl_discord/helper/__init__.py # src/cpl_discord/service/__init__.py # src/cpl_discord/service/discord_bot_service.py # src/cpl_discord/service/discord_bot_service_abc.py # src/cpl_discord/service/discord_service.py # src/cpl_query/__init__.py # src/cpl_query/base/__init__.py # src/cpl_query/base/queryable_abc.py # src/cpl_query/cpl-query.json # src/cpl_query/enumerable/__init__.py # src/cpl_query/extension/__init__.py # src/cpl_query/iterable/__init__.py
This commit is contained in:
		| @@ -39,7 +39,7 @@ class Schematic(GenerateSchematicABC): | ||||
|                     [] | ||||
|                 ) | ||||
|         """ | ||||
|         return self.build_code_str(code, Name=self._class_name) | ||||
|         return self.build_code_str(code, Name=self._class_name, NameLower=self._class_name.lower()) | ||||
|  | ||||
|     @classmethod | ||||
|     def register(cls): | ||||
|   | ||||
| @@ -18,7 +18,8 @@ from cpl_core.type import T | ||||
| class ServiceProvider(ServiceProviderABC): | ||||
|     r"""Provider for the services | ||||
|  | ||||
|     Parameter: | ||||
|     Parameter | ||||
|     --------- | ||||
|         service_descriptors: list[:class:`cpl_core.dependency_injection.service_descriptor.ServiceDescriptor`] | ||||
|             Descriptor of the service | ||||
|         config: :class:`cpl_core.configuration.configuration_abc.ConfigurationABC` | ||||
| @@ -27,12 +28,7 @@ class ServiceProvider(ServiceProviderABC): | ||||
|             Database representation | ||||
|     """ | ||||
|  | ||||
|     def __init__( | ||||
|         self, | ||||
|         service_descriptors: list[ServiceDescriptor], | ||||
|         config: ConfigurationABC, | ||||
|         db_context: Optional[DatabaseContextABC], | ||||
|     ): | ||||
|     def __init__(self, service_descriptors: list[ServiceDescriptor], config: ConfigurationABC, db_context: Optional[DatabaseContextABC]): | ||||
|         ServiceProviderABC.__init__(self) | ||||
|  | ||||
|         self._service_descriptors: list[ServiceDescriptor] = service_descriptors | ||||
| @@ -49,9 +45,7 @@ class ServiceProvider(ServiceProviderABC): | ||||
|  | ||||
|     def _get_service(self, parameter: Parameter) -> Optional[object]: | ||||
|         for descriptor in self._service_descriptors: | ||||
|             if descriptor.service_type == parameter.annotation or issubclass( | ||||
|                 descriptor.service_type, parameter.annotation | ||||
|             ): | ||||
|             if descriptor.service_type == parameter.annotation or issubclass(descriptor.service_type, parameter.annotation): | ||||
|                 if descriptor.implementation is not None: | ||||
|                     return descriptor.implementation | ||||
|  | ||||
| @@ -63,7 +57,7 @@ class ServiceProvider(ServiceProviderABC): | ||||
|  | ||||
|         # raise Exception(f'Service {parameter.annotation} not found') | ||||
|  | ||||
|     def _get_services(self, t: type) -> list[Optional[object]]: | ||||
|     def _get_services(self, t: type, *args, **kwargs) -> list[Optional[object]]: | ||||
|         implementations = [] | ||||
|         for descriptor in self._service_descriptors: | ||||
|             if descriptor.service_type == t or issubclass(descriptor.service_type, t): | ||||
| @@ -71,7 +65,7 @@ class ServiceProvider(ServiceProviderABC): | ||||
|                     implementations.append(descriptor.implementation) | ||||
|                     continue | ||||
|  | ||||
|                 implementation = self.build_service(descriptor.service_type) | ||||
|                 implementation = self.build_service(descriptor.service_type, *args, **kwargs) | ||||
|                 if descriptor.lifetime == ServiceLifetimeEnum.singleton: | ||||
|                     descriptor.implementation = implementation | ||||
|  | ||||
| @@ -83,7 +77,8 @@ class ServiceProvider(ServiceProviderABC): | ||||
|         params = [] | ||||
|         for param in sig.parameters.items(): | ||||
|             parameter = param[1] | ||||
|             if parameter.name != "self" and parameter.annotation != Parameter.empty: | ||||
|             if parameter.name != 'self' and parameter.annotation != Parameter.empty: | ||||
|  | ||||
|                 if typing.get_origin(parameter.annotation) == list: | ||||
|                     params.append(self._get_services(typing.get_args(parameter.annotation)[0])) | ||||
|  | ||||
| @@ -107,7 +102,7 @@ class ServiceProvider(ServiceProviderABC): | ||||
|  | ||||
|         return params | ||||
|  | ||||
|     def build_service(self, service_type: type) -> object: | ||||
|     def build_service(self, service_type: type, *args, **kwargs) -> object: | ||||
|         for descriptor in self._service_descriptors: | ||||
|             if descriptor.service_type == service_type or issubclass(descriptor.service_type, service_type): | ||||
|                 if descriptor.implementation is not None: | ||||
| @@ -120,18 +115,16 @@ class ServiceProvider(ServiceProviderABC): | ||||
|         sig = signature(service_type.__init__) | ||||
|         params = self.build_by_signature(sig) | ||||
|  | ||||
|         return service_type(*params) | ||||
|         return service_type(*params, *args, **kwargs) | ||||
|  | ||||
|     def set_scope(self, scope: ScopeABC): | ||||
|         self._scope = scope | ||||
|  | ||||
|     def create_scope(self) -> ScopeABC: | ||||
|         sb = ScopeBuilder( | ||||
|             ServiceProvider(copy.deepcopy(self._service_descriptors), self._configuration, self._database_context) | ||||
|         ) | ||||
|         sb = ScopeBuilder(ServiceProvider(copy.deepcopy(self._service_descriptors), self._configuration, self._database_context)) | ||||
|         return sb.build() | ||||
|  | ||||
|     def get_service(self, service_type: T) -> Optional[T]: | ||||
|     def get_service(self, service_type: T, *args, **kwargs) -> Optional[T]: | ||||
|         result = self._find_service(service_type) | ||||
|  | ||||
|         if result is None: | ||||
| @@ -140,21 +133,17 @@ class ServiceProvider(ServiceProviderABC): | ||||
|         if result.implementation is not None: | ||||
|             return result.implementation | ||||
|  | ||||
|         implementation = self.build_service(service_type) | ||||
|         if ( | ||||
|             result.lifetime == ServiceLifetimeEnum.singleton | ||||
|             or result.lifetime == ServiceLifetimeEnum.scoped | ||||
|             and self._scope is not None | ||||
|         ): | ||||
|         implementation = self.build_service(service_type, *args, **kwargs) | ||||
|         if result.lifetime == ServiceLifetimeEnum.singleton or result.lifetime == ServiceLifetimeEnum.scoped and self._scope is not None: | ||||
|             result.implementation = implementation | ||||
|  | ||||
|         return implementation | ||||
|  | ||||
|     def get_services(self, service_type: T) -> list[Optional[T]]: | ||||
|     def get_services(self, service_type: T, *args, **kwargs) -> list[Optional[T]]: | ||||
|         implementations = [] | ||||
|  | ||||
|         if typing.get_origin(service_type) != list: | ||||
|             raise Exception(f"Invalid type {service_type}! Expected list of type") | ||||
|             raise Exception(f'Invalid type {service_type}! Expected list of type') | ||||
|  | ||||
|         implementations.extend(self._get_services(typing.get_args(service_type)[0])) | ||||
|  | ||||
|   | ||||
| @@ -10,14 +10,14 @@ from cpl_core.type import T | ||||
| class ServiceProviderABC(ABC): | ||||
|     r"""ABC for the class :class:`cpl_core.dependency_injection.service_provider.ServiceProvider`""" | ||||
|  | ||||
|     _provider: Optional["ServiceProviderABC"] = None | ||||
|     _provider: Optional['ServiceProviderABC'] = None | ||||
|  | ||||
|     @abstractmethod | ||||
|     def __init__(self): | ||||
|         pass | ||||
|  | ||||
|     @classmethod | ||||
|     def set_global_provider(cls, provider: "ServiceProviderABC"): | ||||
|     def set_global_provider(cls, provider: 'ServiceProviderABC'): | ||||
|         cls._provider = provider | ||||
|  | ||||
|     @abstractmethod | ||||
| @@ -25,14 +25,16 @@ class ServiceProviderABC(ABC): | ||||
|         pass | ||||
|  | ||||
|     @abstractmethod | ||||
|     def build_service(self, service_type: type) -> object: | ||||
|     def build_service(self, service_type: type, *args, **kwargs) -> object: | ||||
|         r"""Creates instance of given type | ||||
|  | ||||
|         Parameter: | ||||
|         Parameter | ||||
|         --------- | ||||
|             instance_type: :class:`type` | ||||
|                 The type of the searched instance | ||||
|  | ||||
|         Returns: | ||||
|         Returns | ||||
|         ------- | ||||
|             Object of the given type | ||||
|         """ | ||||
|         pass | ||||
| @@ -41,7 +43,8 @@ class ServiceProviderABC(ABC): | ||||
|     def set_scope(self, scope: ScopeABC): | ||||
|         r"""Sets the scope of service provider | ||||
|  | ||||
|         Parameter: | ||||
|         Parameter | ||||
|         --------- | ||||
|             Object of type :class:`cpl_core.dependency_injection.scope_abc.ScopeABC` | ||||
|                 Service scope | ||||
|         """ | ||||
| @@ -51,33 +54,38 @@ class ServiceProviderABC(ABC): | ||||
|     def create_scope(self) -> ScopeABC: | ||||
|         r"""Creates a service scope | ||||
|  | ||||
|         Returns: | ||||
|         Returns | ||||
|         ------- | ||||
|             Object of type :class:`cpl_core.dependency_injection.scope_abc.ScopeABC` | ||||
|         """ | ||||
|         pass | ||||
|  | ||||
|     @abstractmethod | ||||
|     def get_service(self, instance_type: Type[T]) -> Optional[T]: | ||||
|     def get_service(self, instance_type: T, *args, **kwargs) -> Optional[T]: | ||||
|         r"""Returns instance of given type | ||||
|  | ||||
|         Parameter: | ||||
|         Parameter | ||||
|         --------- | ||||
|             instance_type: :class:`cpl_core.type.T` | ||||
|                 The type of the searched instance | ||||
|  | ||||
|         Returns: | ||||
|         Returns | ||||
|         ------- | ||||
|             Object of type Optional[:class:`cpl_core.type.T`] | ||||
|         """ | ||||
|         pass | ||||
|  | ||||
|     @abstractmethod | ||||
|     def get_services(self, service_type: T) -> list[Optional[T]]: | ||||
|     def get_services(self, service_type: T, *args, **kwargs) -> list[Optional[T]]: | ||||
|         r"""Returns instance of given type | ||||
|  | ||||
|         Parameter: | ||||
|         Parameter | ||||
|         --------- | ||||
|             instance_type: :class:`cpl_core.type.T` | ||||
|                 The type of the searched instance | ||||
|  | ||||
|         Returns: | ||||
|         Returns | ||||
|         ------- | ||||
|             Object of type list[Optional[:class:`cpl_core.type.T`] | ||||
|         """ | ||||
|         pass | ||||
| @@ -86,10 +94,12 @@ class ServiceProviderABC(ABC): | ||||
|     def inject(cls, f=None): | ||||
|         r"""Decorator to allow injection into static and class methods | ||||
|  | ||||
|         Parameter: | ||||
|         Parameter | ||||
|         --------- | ||||
|             f: Callable | ||||
|  | ||||
|         Returns: | ||||
|         Returns | ||||
|         ------- | ||||
|             function | ||||
|         """ | ||||
|         if f is None: | ||||
| @@ -98,9 +108,9 @@ class ServiceProviderABC(ABC): | ||||
|         @functools.wraps(f) | ||||
|         def inner(*args, **kwargs): | ||||
|             if cls._provider is None: | ||||
|                 raise Exception(f"{cls.__name__} not build!") | ||||
|                 raise Exception(f'{cls.__name__} not build!') | ||||
|  | ||||
|             injection = cls._provider.build_by_signature(signature(f)) | ||||
|             return f(*injection, *args, **kwargs) | ||||
|             injection = [x for x in cls._provider.build_by_signature(signature(f)) if x is not None] | ||||
|             return f(*args, *injection, **kwargs) | ||||
|  | ||||
|         return inner | ||||
|   | ||||
| @@ -7,37 +7,51 @@ from cpl_core.utils import String | ||||
|  | ||||
|  | ||||
| class Event(GenerateSchematicABC): | ||||
|  | ||||
|     def __init__(self, name: str, schematic: str, path: str): | ||||
|         GenerateSchematicABC.__init__(self, name, schematic, path) | ||||
|  | ||||
|         event = None | ||||
|         event_class = None | ||||
|  | ||||
|         from cpl_discord.discord_event_types_enum import DiscordEventTypesEnum | ||||
|  | ||||
|         for event_type in DiscordEventTypesEnum: | ||||
|             event_name = event_type.value.__name__.replace("ABC", "") | ||||
|             event_name = event_type.value.__name__.replace("ABC", '') | ||||
|  | ||||
|             if event_name in name: | ||||
|             if name.endswith(event_name): | ||||
|                 name = name.replace(event_name, "") | ||||
|                 event = event_name | ||||
|                 event_class = event_type.value | ||||
|                 break | ||||
|  | ||||
|         if event is None: | ||||
|             Console.error(f"No valid event found in name {name}") | ||||
|             Console.write_line("Available events:") | ||||
|             Console.error(f'No valid event found in name {name}') | ||||
|             Console.write_line('Available events:') | ||||
|             for event_type in DiscordEventTypesEnum: | ||||
|                 Console.write_line(f'\t{event_type.value.__name__.replace("ABC", "")}') | ||||
|             sys.exit() | ||||
|  | ||||
|         self._event_class = f"{event}ABC" | ||||
|         self._name = f'{String.convert_to_snake_case(self._event_class.replace("ABC", ""))}_{schematic}.py' | ||||
|         self._class_name = f'{self._event_class.replace("ABC", "")}{String.first_to_upper(schematic)}' | ||||
|         if name != "": | ||||
|             self._name = f"{String.convert_to_snake_case(name)}_{self._name}" | ||||
|             self._class_name = f"{String.first_to_upper(name)}{self._class_name}" | ||||
|         self._event_class_name = f'{event}ABC' | ||||
|         event_snake_case = String.convert_to_snake_case(self._event_class_name.replace("ABC", "")) | ||||
|  | ||||
|         if event_snake_case.lower() not in dir(event_class): | ||||
|             Console.error(f'Error in event {event}: Function {event_snake_case} not found!') | ||||
|             sys.exit() | ||||
|  | ||||
|         self._name = f'{event_snake_case}_{schematic}.py' | ||||
|         self._class_name = f'{self._event_class_name.replace("ABC", "")}{String.first_to_upper(schematic)}' | ||||
|  | ||||
|         from inspect import signature | ||||
|         self._func_name = event_snake_case | ||||
|         self._signature = str(signature(getattr(event_class, event_snake_case)))[1:][:-1] | ||||
|  | ||||
|         if name != '': | ||||
|                 self._name = f'{String.convert_to_snake_case(name)}_{self._name}' | ||||
|                 self._class_name = f'{String.first_to_upper(name)}{self._class_name}' | ||||
|  | ||||
|     def get_code(self) -> str: | ||||
|         code = """\ | ||||
|         import discord | ||||
|         from cpl_core.logging import LoggerABC | ||||
|         from cpl_discord.events import $EventClass | ||||
|         from cpl_discord.service import DiscordBotServiceABC | ||||
| @@ -50,16 +64,26 @@ class Event(GenerateSchematicABC): | ||||
|                     logger: LoggerABC, | ||||
|                     bot: DiscordBotServiceABC, | ||||
|             ): | ||||
|                 OnReadyABC.__init__(self) | ||||
|                 $EventClass.__init__(self) | ||||
|          | ||||
|                 self._logger = logger | ||||
|                 self._bot = bot | ||||
|          | ||||
|             async def on_ready(self): | ||||
|             async def $Func($Signature): | ||||
|                 pass | ||||
|         """ | ||||
|         return self.build_code_str(code, Name=self._class_name, EventClass=self._event_class) | ||||
|         return self.build_code_str( | ||||
|             code, | ||||
|             Name=self._class_name, | ||||
|             EventClass=self._event_class_name, | ||||
|             Func=self._func_name, | ||||
|             Signature=self._signature | ||||
|         ) | ||||
|  | ||||
|     @classmethod | ||||
|     def register(cls): | ||||
|         GenerateSchematicABC.register(cls, "event", []) | ||||
|         GenerateSchematicABC.register( | ||||
|             cls, | ||||
|             'event', | ||||
|             [] | ||||
|         ) | ||||
|   | ||||
| @@ -47,6 +47,11 @@ from cpl_discord.events.on_reaction_clear_emoji_abc import OnReactionClearEmojiA | ||||
| from cpl_discord.events.on_reaction_remove_abc import OnReactionRemoveABC | ||||
| from cpl_discord.events.on_ready_abc import OnReadyABC | ||||
| from cpl_discord.events.on_resume_abc import OnResumeABC | ||||
| from cpl_discord.events.on_scheduled_event_create_abc import OnScheduledEventCreateABC | ||||
| from cpl_discord.events.on_scheduled_event_delete_abc import OnScheduledEventDeleteABC | ||||
| from cpl_discord.events.on_scheduled_event_update_abc import OnScheduledEventUpdateABC | ||||
| from cpl_discord.events.on_scheduled_event_user_add_abc import OnScheduledEventUserAddABC | ||||
| from cpl_discord.events.on_scheduled_event_user_remove_abc import OnScheduledEventUserRemoveABC | ||||
| from cpl_discord.events.on_typing_abc import OnTypingABC | ||||
| from cpl_discord.events.on_user_update_abc import OnUserUpdateABC | ||||
| from cpl_discord.events.on_voice_state_update_abc import OnVoiceStateUpdateABC | ||||
| @@ -76,6 +81,11 @@ class DiscordEventTypesEnum(Enum): | ||||
|     on_guild_role_delete = OnGuildRoleDeleteABC | ||||
|     on_guild_role_update = OnGuildRoleUpdateABC | ||||
|     on_guild_unavailable = OnGuildUnavailableABC | ||||
|     on_scheduled_event_create = OnScheduledEventCreateABC | ||||
|     on_scheduled_event_delete = OnScheduledEventDeleteABC | ||||
|     on_scheduled_event_update = OnScheduledEventUpdateABC | ||||
|     on_scheduled_event_user_add = OnScheduledEventUserAddABC | ||||
|     on_scheduled_event_user_remove = OnScheduledEventUserRemoveABC | ||||
|     on_guild_update = OnGuildUpdateABC | ||||
|     on_invite_create = OnInviteCreateABC | ||||
|     on_invite_delete = OnInviteDeleteABC | ||||
|   | ||||
							
								
								
									
										11
									
								
								src/cpl_discord/events/on_scheduled_event_create_abc.py
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										11
									
								
								src/cpl_discord/events/on_scheduled_event_create_abc.py
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,11 @@ | ||||
| from abc import ABC, abstractmethod | ||||
| import discord | ||||
|  | ||||
|  | ||||
| class OnScheduledEventCreateABC(ABC): | ||||
|  | ||||
|     @abstractmethod | ||||
|     def __init__(self): pass | ||||
|  | ||||
|     @abstractmethod | ||||
|     async def on_scheduled_event_create(self, event: discord.ScheduledEvent): pass | ||||
							
								
								
									
										11
									
								
								src/cpl_discord/events/on_scheduled_event_delete_abc.py
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										11
									
								
								src/cpl_discord/events/on_scheduled_event_delete_abc.py
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,11 @@ | ||||
| from abc import ABC, abstractmethod | ||||
| import discord | ||||
|  | ||||
|  | ||||
| class OnScheduledEventDeleteABC(ABC): | ||||
|  | ||||
|     @abstractmethod | ||||
|     def __init__(self): pass | ||||
|  | ||||
|     @abstractmethod | ||||
|     async def on_scheduled_event_delete(self, event: discord.ScheduledEvent): pass | ||||
							
								
								
									
										11
									
								
								src/cpl_discord/events/on_scheduled_event_update_abc.py
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										11
									
								
								src/cpl_discord/events/on_scheduled_event_update_abc.py
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,11 @@ | ||||
| from abc import ABC, abstractmethod | ||||
| import discord | ||||
|  | ||||
|  | ||||
| class OnScheduledEventUpdateABC(ABC): | ||||
|  | ||||
|     @abstractmethod | ||||
|     def __init__(self): pass | ||||
|  | ||||
|     @abstractmethod | ||||
|     async def on_scheduled_event_update(self, before: discord.ScheduledEvent, after: discord.ScheduledEvent): pass | ||||
							
								
								
									
										11
									
								
								src/cpl_discord/events/on_scheduled_event_user_add_abc.py
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										11
									
								
								src/cpl_discord/events/on_scheduled_event_user_add_abc.py
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,11 @@ | ||||
| from abc import ABC, abstractmethod | ||||
| import discord | ||||
|  | ||||
|  | ||||
| class OnScheduledEventUserAddABC(ABC): | ||||
|  | ||||
|     @abstractmethod | ||||
|     def __init__(self): pass | ||||
|  | ||||
|     @abstractmethod | ||||
|     async def on_scheduled_event_user_add(self, event: discord.ScheduledEvent, user: discord.User): pass | ||||
							
								
								
									
										11
									
								
								src/cpl_discord/events/on_scheduled_event_user_remove_abc.py
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										11
									
								
								src/cpl_discord/events/on_scheduled_event_user_remove_abc.py
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,11 @@ | ||||
| from abc import ABC, abstractmethod | ||||
| import discord | ||||
|  | ||||
|  | ||||
| class OnScheduledEventUserRemoveABC(ABC): | ||||
|  | ||||
|     @abstractmethod | ||||
|     def __init__(self): pass | ||||
|  | ||||
|     @abstractmethod | ||||
|     async def on_scheduled_event_user_remove(self, event: discord.ScheduledEvent, user: discord.User): pass | ||||
| @@ -13,14 +13,17 @@ from cpl_query.extension.list import List | ||||
|  | ||||
|  | ||||
| class DiscordBotService(DiscordBotServiceABC): | ||||
|  | ||||
|     def __init__( | ||||
|         self, | ||||
|         config: ConfigurationABC, | ||||
|         logger: LoggerABC, | ||||
|         discord_bot_settings: DiscordBotSettings, | ||||
|         env: ApplicationEnvironmentABC, | ||||
|         logging_st: LoggingSettings, | ||||
|         discord_service: DiscordServiceABC, | ||||
|             self, | ||||
|             config: ConfigurationABC, | ||||
|             logger: LoggerABC, | ||||
|             discord_bot_settings: DiscordBotSettings, | ||||
|             env: ApplicationEnvironmentABC, | ||||
|             logging_st: LoggingSettings, | ||||
|             discord_service: DiscordServiceABC, | ||||
|             *args, | ||||
|             **kwargs | ||||
|     ): | ||||
|         # services | ||||
|         self._config = config | ||||
| @@ -34,56 +37,57 @@ class DiscordBotService(DiscordBotServiceABC): | ||||
|  | ||||
|         # setup super | ||||
|         DiscordBotServiceABC.__init__( | ||||
|             self, command_prefix=self._discord_settings.prefix, help_command=None, intents=discord.Intents().all() | ||||
|             self, | ||||
|             *args, | ||||
|             command_prefix=self._discord_settings.prefix, help_command=None, intents=discord.Intents().all(), | ||||
|             **kwargs | ||||
|         ) | ||||
|         self._base = super(DiscordBotServiceABC, self) | ||||
|  | ||||
|     @staticmethod | ||||
|     def _is_string_invalid(x): | ||||
|         return x is None or x == "" | ||||
|         return x is None or x == '' | ||||
|  | ||||
|     def _get_settings(self, settings_from_config: DiscordBotSettings) -> DiscordBotSettings: | ||||
|         new_settings = DiscordBotSettings() | ||||
|         token = None if settings_from_config is None else settings_from_config.token | ||||
|         prefix = None if settings_from_config is None else settings_from_config.prefix | ||||
|         env_token = self._config.get_configuration("TOKEN") | ||||
|         env_prefix = self._config.get_configuration("PREFIX") | ||||
|         env_token = self._config.get_configuration('TOKEN') | ||||
|         env_prefix = self._config.get_configuration('PREFIX') | ||||
|  | ||||
|         new_settings.from_dict( | ||||
|             { | ||||
|                 "Token": env_token if token is None or token == "" else token, | ||||
|                 "Prefix": ("! " if self._is_string_invalid(env_prefix) else env_prefix) | ||||
|                 if self._is_string_invalid(prefix) | ||||
|                 else prefix, | ||||
|             } | ||||
|         ) | ||||
|         if new_settings.token is None or new_settings.token == "": | ||||
|             raise Exception("You have to configure discord token by appsettings or environment variables") | ||||
|         new_settings.from_dict({ | ||||
|             'Token': env_token if token is None or token == '' else token, | ||||
|             'Prefix': | ||||
|                 ('! ' if self._is_string_invalid(env_prefix) else env_prefix) | ||||
|                 if self._is_string_invalid(prefix) else prefix | ||||
|         }) | ||||
|         if new_settings.token is None or new_settings.token == '': | ||||
|             raise Exception('You have to configure discord token by appsettings or environment variables') | ||||
|         return new_settings | ||||
|  | ||||
|     async def start_async(self): | ||||
|         self._logger.trace(__name__, "Try to connect to discord") | ||||
|         self._logger.trace(__name__, 'Try to connect to discord') | ||||
|         await self.start(self._discord_settings.token) | ||||
|         # continue at on_ready | ||||
|  | ||||
|     async def stop_async(self): | ||||
|         self._logger.trace(__name__, "Try to disconnect from discord") | ||||
|         self._logger.trace(__name__, 'Try to disconnect from discord') | ||||
|         try: | ||||
|             await self.close() | ||||
|         except Exception as e: | ||||
|             self._logger.error(__name__, "Stop failed", e) | ||||
|             self._logger.error(__name__, 'Stop failed', e) | ||||
|  | ||||
|     async def on_ready(self): | ||||
|         self._logger.info(__name__, "Connected to discord") | ||||
|         self._logger.info(__name__, 'Connected to discord') | ||||
|  | ||||
|         self._logger.header(f"{self.user.name}:") | ||||
|         self._logger.header(f'{self.user.name}:') | ||||
|         if self._logging_st.console.value >= LoggingLevelEnum.INFO.value: | ||||
|             Console.banner(self._env.application_name if self._env.application_name != "" else "A bot") | ||||
|             Console.banner(self._env.application_name if self._env.application_name != '' else 'A bot') | ||||
|  | ||||
|         await self._discord_service.init(self) | ||||
|         await self.wait_until_ready() | ||||
|         await self.tree.sync() | ||||
|         self._logger.debug(__name__, f"Finished syncing commands") | ||||
|         self._logger.debug(__name__, f'Finished syncing commands') | ||||
|  | ||||
|         await self._discord_service.on_ready() | ||||
|  | ||||
|   | ||||
| @@ -7,22 +7,19 @@ from cpl_query.extension.list import List | ||||
|  | ||||
|  | ||||
| class DiscordBotServiceABC(commands.Bot): | ||||
|     def __init__(self, **kwargs): | ||||
|         commands.Bot.__init__(self, **kwargs) | ||||
|  | ||||
|     def __init__(self, *args, **kwargs): | ||||
|         commands.Bot.__init__(self, *args, **kwargs) | ||||
|  | ||||
|     @abstractmethod | ||||
|     async def start_async(self): | ||||
|         pass | ||||
|     async def start_async(self): pass | ||||
|  | ||||
|     @abstractmethod | ||||
|     async def stop_async(self): | ||||
|         pass | ||||
|     async def stop_async(self): pass | ||||
|  | ||||
|     @abstractmethod | ||||
|     async def on_ready(self): | ||||
|         pass | ||||
|     async def on_ready(self): pass | ||||
|  | ||||
|     @property | ||||
|     @abstractmethod | ||||
|     def guilds(self) -> List[Guild]: | ||||
|         pass | ||||
|     def guilds(self) -> List[Guild]: pass | ||||
|   | ||||
| @@ -57,6 +57,11 @@ from cpl_discord.events.on_reaction_clear_emoji_abc import OnReactionClearEmojiA | ||||
| from cpl_discord.events.on_reaction_remove_abc import OnReactionRemoveABC | ||||
| from cpl_discord.events.on_ready_abc import OnReadyABC | ||||
| from cpl_discord.events.on_resume_abc import OnResumeABC | ||||
| from cpl_discord.events.on_scheduled_event_create_abc import OnScheduledEventCreateABC | ||||
| from cpl_discord.events.on_scheduled_event_delete_abc import OnScheduledEventDeleteABC | ||||
| from cpl_discord.events.on_scheduled_event_update_abc import OnScheduledEventUpdateABC | ||||
| from cpl_discord.events.on_scheduled_event_user_add_abc import OnScheduledEventUserAddABC | ||||
| from cpl_discord.events.on_scheduled_event_user_remove_abc import OnScheduledEventUserRemoveABC | ||||
| from cpl_discord.events.on_typing_abc import OnTypingABC | ||||
| from cpl_discord.events.on_user_update_abc import OnUserUpdateABC | ||||
| from cpl_discord.events.on_voice_state_update_abc import OnVoiceStateUpdateABC | ||||
| @@ -66,7 +71,13 @@ from cpl_discord.service.discord_service_abc import DiscordServiceABC | ||||
|  | ||||
|  | ||||
| class DiscordService(DiscordServiceABC, commands.Cog, metaclass=DiscordCogMeta): | ||||
|     def __init__(self, logger: LoggerABC, dc_collection: DiscordCollectionABC, services: ServiceProviderABC): | ||||
|  | ||||
|     def __init__( | ||||
|             self, | ||||
|             logger: LoggerABC, | ||||
|             dc_collection: DiscordCollectionABC, | ||||
|             services: ServiceProviderABC | ||||
|     ): | ||||
|         DiscordServiceABC.__init__(self) | ||||
|         self._logger = logger | ||||
|         self._collection = dc_collection | ||||
| @@ -81,8 +92,8 @@ class DiscordService(DiscordServiceABC, commands.Cog, metaclass=DiscordCogMeta): | ||||
|             event_instance = self._services.get_service(event_type) | ||||
|  | ||||
|             func_name = event.__name__ | ||||
|             if func_name.endswith("ABC"): | ||||
|                 func_name = func_name.replace("ABC", "") | ||||
|             if func_name.endswith('ABC'): | ||||
|                 func_name = func_name.replace('ABC', '') | ||||
|  | ||||
|             func_name = String.convert_to_snake_case(func_name) | ||||
|  | ||||
| @@ -90,286 +101,305 @@ class DiscordService(DiscordServiceABC, commands.Cog, metaclass=DiscordCogMeta): | ||||
|                 func = getattr(event_instance, func_name) | ||||
|                 await func(*args, **kwargs) | ||||
|             except Exception as e: | ||||
|                 self._logger.error(__name__, f"Cannot execute {func_name} of {type(event_instance).__name__}", e) | ||||
|                 self._logger.error(__name__, f'Cannot execute {func_name} of {type(event_instance).__name__}', e) | ||||
|  | ||||
|     async def init(self, bot: commands.Bot): | ||||
|         try: | ||||
|             await bot.add_cog(self) | ||||
|         except Exception as e: | ||||
|             self._logger.error(__name__, f"{type(self).__name__} initialization failed", e) | ||||
|             self._logger.error(__name__, f'{type(self).__name__} initialization failed', e) | ||||
|  | ||||
|         try: | ||||
|             for command_type in self._collection.get_commands(): | ||||
|                 self._logger.trace(__name__, f"Register command {command_type.__name__}") | ||||
|                 self._logger.trace(__name__, f'Register command {command_type.__name__}') | ||||
|                 command: Cog = self._services.get_service(command_type) | ||||
|                 if command is None: | ||||
|                     self._logger.warn(__name__, f"Instance of {command_type.__name__} not found") | ||||
|                     self._logger.warn(__name__, f'Instance of {command_type.__name__} not found') | ||||
|                     continue | ||||
|                 await bot.add_cog(command) | ||||
|         except Exception as e: | ||||
|             self._logger.error(__name__, f"Registration of commands failed", e) | ||||
|             self._logger.error(__name__, f'Registration of commands failed', e) | ||||
|  | ||||
|     @commands.Cog.listener() | ||||
|     async def on_connect(self): | ||||
|         self._logger.trace(__name__, f"Received on_connect") | ||||
|         self._logger.trace(__name__, f'Received on_connect') | ||||
|         await self._handle_event(OnConnectABC) | ||||
|  | ||||
|     @commands.Cog.listener() | ||||
|     async def on_command(self, ctx: Context): | ||||
|         self._logger.trace(__name__, f"Received on_command") | ||||
|         self._logger.trace(__name__, f'Received on_command') | ||||
|         await self._handle_event(OnCommandABC, ctx) | ||||
|  | ||||
|     @commands.Cog.listener() | ||||
|     async def on_command_error(self, ctx: Context, error: CommandError): | ||||
|         self._logger.trace(__name__, f"Received on_command_error") | ||||
|         self._logger.trace(__name__, f'Received on_command_error') | ||||
|         await self._handle_event(OnCommandErrorABC, ctx, error) | ||||
|  | ||||
|     @commands.Cog.listener() | ||||
|     async def on_command_completion(self, ctx: Context): | ||||
|         self._logger.trace(__name__, f"Received on_command_completion") | ||||
|         self._logger.trace(__name__, f'Received on_command_completion') | ||||
|         await self._handle_event(OnCommandCompletionABC, ctx) | ||||
|  | ||||
|     @commands.Cog.listener() | ||||
|     async def on_disconnect(self): | ||||
|         self._logger.trace(__name__, f"Received on_disconnect") | ||||
|         self._logger.trace(__name__, f'Received on_disconnect') | ||||
|         await self._handle_event(OnDisconnectABC) | ||||
|  | ||||
|     @commands.Cog.listener() | ||||
|     async def on_error(self, event: str, *args, **kwargs): | ||||
|         self._logger.trace(__name__, f"Received on_error") | ||||
|         self._logger.trace(__name__, f'Received on_error') | ||||
|         await self._handle_event(OnErrorABC, event, *args, **kwargs) | ||||
|  | ||||
|     async def on_ready(self): | ||||
|         self._logger.trace(__name__, f"Received on_ready") | ||||
|         self._logger.trace(__name__, f'Received on_ready') | ||||
|         await self._handle_event(OnReadyABC) | ||||
|  | ||||
|     @commands.Cog.listener() | ||||
|     async def on_resume(self): | ||||
|         self._logger.trace(__name__, f"Received on_resume") | ||||
|         self._logger.trace(__name__, f'Received on_resume') | ||||
|         await self._handle_event(OnResumeABC) | ||||
|  | ||||
|     @commands.Cog.listener() | ||||
|     async def on_error(self, event: str, *args, **kwargs): | ||||
|         self._logger.trace(__name__, f"Received on_error:\n\t{event}\n\t{args}\n\t{kwargs}") | ||||
|         self._logger.trace(__name__, f'Received on_error:\n\t{event}\n\t{args}\n\t{kwargs}') | ||||
|         await self._handle_event(OnReadyABC, event, *args, **kwargs) | ||||
|  | ||||
|     @commands.Cog.listener() | ||||
|     async def on_typing( | ||||
|         self, channel: discord.abc.Messageable, user: Union[discord.User, discord.Member], when: datetime | ||||
|     ): | ||||
|         self._logger.trace(__name__, f"Received on_typing:\n\t{channel}\n\t{user}\n\t{when}") | ||||
|     async def on_typing(self, channel: discord.abc.Messageable, user: Union[discord.User, discord.Member], when: datetime): | ||||
|         self._logger.trace(__name__, f'Received on_typing:\n\t{channel}\n\t{user}\n\t{when}') | ||||
|         await self._handle_event(OnTypingABC, channel, user, when) | ||||
|  | ||||
|     @commands.Cog.listener() | ||||
|     async def on_message(self, message: discord.Message): | ||||
|         self._logger.trace(__name__, f"Received on_message:\n\t{message}") | ||||
|         self._logger.trace(__name__, f'Received on_message:\n\t{message}') | ||||
|         await self._handle_event(OnMessageABC, message) | ||||
|  | ||||
|     @commands.Cog.listener() | ||||
|     async def on_message_delete(self, message: discord.Message): | ||||
|         self._logger.trace(__name__, f"Received on_message_delete:\n\t{message}") | ||||
|         self._logger.trace(__name__, f'Received on_message_delete:\n\t{message}') | ||||
|         await self._handle_event(OnMessageDeleteABC, message) | ||||
|  | ||||
|     @commands.Cog.listener() | ||||
|     async def on_bulk_message_delete(self, messages: list[discord.Message]): | ||||
|         self._logger.trace(__name__, f"Received on_bulk_message_delete:\n\t{len(messages)}") | ||||
|         self._logger.trace(__name__, f'Received on_bulk_message_delete:\n\t{len(messages)}') | ||||
|         await self._handle_event(OnBulkMessageDeleteABC, messages) | ||||
|  | ||||
|     @commands.Cog.listener() | ||||
|     async def on_message_edit(self, before: discord.Message, after: discord.Message): | ||||
|         self._logger.trace(__name__, f"Received on_message_edit:\n\t{before}\n\t{after}") | ||||
|         self._logger.trace(__name__, f'Received on_message_edit:\n\t{before}\n\t{after}') | ||||
|         await self._handle_event(OnMessageEditABC, before, after) | ||||
|  | ||||
|     @commands.Cog.listener() | ||||
|     async def on_raw_reaction_add(self, payload: RawReactionActionEvent): | ||||
|         self._logger.trace(__name__, f"Received on_raw_reaction_add") | ||||
|         self._logger.trace(__name__, f'Received on_raw_reaction_add') | ||||
|         await self._handle_event(OnRawReactionAddABC, payload) | ||||
|  | ||||
|     @commands.Cog.listener() | ||||
|     async def on_raw_reaction_remove(self, payload: RawReactionActionEvent): | ||||
|         self._logger.trace(__name__, f"Received on_raw_reaction_remove") | ||||
|         self._logger.trace(__name__, f'Received on_raw_reaction_remove') | ||||
|         await self._handle_event(OnRawReactionRemoveABC, payload) | ||||
|  | ||||
|     @commands.Cog.listener() | ||||
|     async def on_raw_reaction_clear(self, payload: RawReactionActionEvent): | ||||
|         self._logger.trace(__name__, f"Received on_raw_reaction_clear") | ||||
|         self._logger.trace(__name__, f'Received on_raw_reaction_clear') | ||||
|         await self._handle_event(OnRawReactionClearABC, payload) | ||||
|  | ||||
|     @commands.Cog.listener() | ||||
|     async def on_raw_reaction_clear_emoji(self, payload: RawReactionActionEvent): | ||||
|         self._logger.trace(__name__, f"Received on_raw_reaction_clear_emoji") | ||||
|         self._logger.trace(__name__, f'Received on_raw_reaction_clear_emoji') | ||||
|         await self._handle_event(OnRawReactionClearEmojiABC, payload) | ||||
|  | ||||
|     @commands.Cog.listener() | ||||
|     async def on_reaction_add(self, reaction: discord.Reaction, user: discord.User): | ||||
|         self._logger.trace(__name__, f"Received on_reaction_add:\n\t{reaction}\n\t{user}") | ||||
|         self._logger.trace(__name__, f'Received on_reaction_add:\n\t{reaction}\n\t{user}') | ||||
|         await self._handle_event(OnReactionAddABC, reaction, user) | ||||
|  | ||||
|     @commands.Cog.listener() | ||||
|     async def on_reaction_remove(self, reaction: discord.Reaction, user: discord.User): | ||||
|         self._logger.trace(__name__, f"Received on_reaction_remove:\n\t{reaction}\n\t{user}") | ||||
|         self._logger.trace(__name__, f'Received on_reaction_remove:\n\t{reaction}\n\t{user}') | ||||
|         await self._handle_event(OnReactionRemoveABC, reaction, user) | ||||
|  | ||||
|     @commands.Cog.listener() | ||||
|     async def on_reaction_clear(self, message: discord.Message, reactions: list[discord.Reaction]): | ||||
|         self._logger.trace(__name__, f"Received on_reaction_reon_reaction_clearmove:\n\t{message}\n\t{len(reactions)}") | ||||
|         self._logger.trace(__name__, f'Received on_reaction_reon_reaction_clearmove:\n\t{message}\n\t{len(reactions)}') | ||||
|         await self._handle_event(OnReactionClearABC, message, reactions) | ||||
|  | ||||
|     @commands.Cog.listener() | ||||
|     async def on_reaction_clear_emoji(self, reaction: discord.Reaction): | ||||
|         self._logger.trace(__name__, f"Received on_reaction_clear_emoji:\n\t{reaction}") | ||||
|         self._logger.trace(__name__, f'Received on_reaction_clear_emoji:\n\t{reaction}') | ||||
|         await self._handle_event(OnReactionClearEmojiABC, reaction) | ||||
|  | ||||
|     @commands.Cog.listener() | ||||
|     async def on_private_channel_delete(self, channel: discord.abc.PrivateChannel): | ||||
|         self._logger.trace(__name__, f"Received on_private_channel_delete:\n\t{channel}") | ||||
|         self._logger.trace(__name__, f'Received on_private_channel_delete:\n\t{channel}') | ||||
|         await self._handle_event(OnPrivateChannelDeleteABC, channel) | ||||
|  | ||||
|     @commands.Cog.listener() | ||||
|     async def on_private_channel_create(self, channel: discord.abc.PrivateChannel): | ||||
|         self._logger.trace(__name__, f"Received on_private_channel_create:\n\t{channel}") | ||||
|         self._logger.trace(__name__, f'Received on_private_channel_create:\n\t{channel}') | ||||
|         await self._handle_event(OnPrivateChannelCreateABC, channel) | ||||
|  | ||||
|     @commands.Cog.listener() | ||||
|     async def on_private_channel_update(self, before: discord.GroupChannel, after: discord.GroupChannel): | ||||
|         self._logger.trace(__name__, f"Received on_private_channel_update:\n\t{before}\n\t{after}") | ||||
|         self._logger.trace(__name__, f'Received on_private_channel_update:\n\t{before}\n\t{after}') | ||||
|         await self._handle_event(OnPrivateChannelUpdateABC, before, after) | ||||
|  | ||||
|     @commands.Cog.listener() | ||||
|     async def on_private_channel_pins_update(self, channel: discord.abc.PrivateChannel, list_pin: Optional[datetime]): | ||||
|         self._logger.trace(__name__, f"Received on_private_channel_pins_update:\n\t{channel}\n\t{list_pin}") | ||||
|         self._logger.trace(__name__, f'Received on_private_channel_pins_update:\n\t{channel}\n\t{list_pin}') | ||||
|         await self._handle_event(OnPrivateChannelPinsUpdateABC, channel, list_pin) | ||||
|  | ||||
|     @commands.Cog.listener() | ||||
|     async def on_guild_channel_delete(self, channel: discord.abc.GuildChannel): | ||||
|         self._logger.trace(__name__, f"Received on_guild_channel_delete:\n\t{channel}") | ||||
|         self._logger.trace(__name__, f'Received on_guild_channel_delete:\n\t{channel}') | ||||
|         await self._handle_event(OnGuildChannelDeleteABC, channel) | ||||
|  | ||||
|     @commands.Cog.listener() | ||||
|     async def on_guild_channel_create(self, channel: discord.abc.GuildChannel): | ||||
|         self._logger.trace(__name__, f"Received on_guild_channel_create:\n\t{channel}") | ||||
|         self._logger.trace(__name__, f'Received on_guild_channel_create:\n\t{channel}') | ||||
|         await self._handle_event(OnGuildChannelCreateABC, channel) | ||||
|  | ||||
|     @commands.Cog.listener() | ||||
|     async def on_guild_channel_update(self, before: discord.abc.GuildChannel, after: discord.abc.GuildChannel): | ||||
|         self._logger.trace(__name__, f"Received on_guild_channel_update:\n\t{before}\n\t{after}") | ||||
|         self._logger.trace(__name__, f'Received on_guild_channel_update:\n\t{before}\n\t{after}') | ||||
|         await self._handle_event(OnGuildChannelUpdateABC, before, after) | ||||
|  | ||||
|     @commands.Cog.listener() | ||||
|     async def on_guild_channel_pins_update(self, channel: discord.abc.GuildChannel, list_pin: Optional[datetime]): | ||||
|         self._logger.trace(__name__, f"Received on_guild_channel_pins_update:\n\t{channel}\n\t{list_pin}") | ||||
|         self._logger.trace(__name__, f'Received on_guild_channel_pins_update:\n\t{channel}\n\t{list_pin}') | ||||
|         await self._handle_event(OnGuildChannelPinsUpdateABC, channel, list_pin) | ||||
|  | ||||
|     @commands.Cog.listener() | ||||
|     async def on_guild_integrations_update(self, guild: discord.Guild): | ||||
|         self._logger.trace(__name__, f"Received on_guild_integrations_update:\n\t{guild}") | ||||
|         self._logger.trace(__name__, f'Received on_guild_integrations_update:\n\t{guild}') | ||||
|         await self._handle_event(OnGuildIntegrationsUpdateABC, guild) | ||||
|  | ||||
|     @commands.Cog.listener() | ||||
|     async def on_webhooks_update(self, channel: discord.abc.GuildChannel): | ||||
|         self._logger.trace(__name__, f"Received on_webhooks_update:\n\t{channel}") | ||||
|         self._logger.trace(__name__, f'Received on_webhooks_update:\n\t{channel}') | ||||
|         await self._handle_event(OnWebhooksUpdateABC, channel) | ||||
|  | ||||
|     @commands.Cog.listener() | ||||
|     async def on_member_join(self, member: discord.Member): | ||||
|         self._logger.trace(__name__, f"Received on_member_join:\n\t{member}") | ||||
|         self._logger.trace(__name__, f'Received on_member_join:\n\t{member}') | ||||
|         await self._handle_event(OnMemberJoinABC, member) | ||||
|  | ||||
|     @commands.Cog.listener() | ||||
|     async def on_member_remove(self, member: discord.Member): | ||||
|         self._logger.trace(__name__, f"Received on_member_remove:\n\t{member}") | ||||
|         self._logger.trace(__name__, f'Received on_member_remove:\n\t{member}') | ||||
|         await self._handle_event(OnMemberRemoveABC, member) | ||||
|  | ||||
|     @commands.Cog.listener() | ||||
|     async def on_member_update(self, before: discord.Member, after: discord.Member): | ||||
|         self._logger.trace(__name__, f"Received on_member_update:\n\t{before}\n\t{after}") | ||||
|         self._logger.trace(__name__, f'Received on_member_update:\n\t{before}\n\t{after}') | ||||
|         await self._handle_event(OnMemberUpdateABC, before, after) | ||||
|  | ||||
|     @commands.Cog.listener() | ||||
|     async def on_user_update(self, before: discord.User, after: discord.User): | ||||
|         self._logger.trace(__name__, f"Received on_user_update:\n\t{before}\n\t{after}") | ||||
|         self._logger.trace(__name__, f'Received on_user_update:\n\t{before}\n\t{after}') | ||||
|         await self._handle_event(OnUserUpdateABC, before, after) | ||||
|  | ||||
|     @commands.Cog.listener() | ||||
|     async def on_guild_join(self, guild: discord.Guild): | ||||
|         self._logger.trace(__name__, f"Received on_guild_join:\n\t{guild}") | ||||
|         self._logger.trace(__name__, f'Received on_guild_join:\n\t{guild}') | ||||
|         await self._handle_event(OnGuildJoinABC, guild) | ||||
|  | ||||
|     @commands.Cog.listener() | ||||
|     async def on_guild_remove(self, guild: discord.Guild): | ||||
|         self._logger.trace(__name__, f"Received on_guild_remove:\n\t{guild}") | ||||
|         self._logger.trace(__name__, f'Received on_guild_remove:\n\t{guild}') | ||||
|         await self._handle_event(OnGuildRemoveABC, guild) | ||||
|  | ||||
|     @commands.Cog.listener() | ||||
|     async def on_guild_update(self, before: discord.Guild, after: discord.Guild): | ||||
|         self._logger.trace(__name__, f"Received on_guild_update:\n\t{before}\n\t{after}") | ||||
|         self._logger.trace(__name__, f'Received on_guild_update:\n\t{before}\n\t{after}') | ||||
|         await self._handle_event(OnGuildUpdateABC, before, after) | ||||
|  | ||||
|     @commands.Cog.listener() | ||||
|     async def on_guild_role_create(self, role: discord.Role): | ||||
|         self._logger.trace(__name__, f"Received on_guild_role_create:\n\t{role}") | ||||
|         self._logger.trace(__name__, f'Received on_guild_role_create:\n\t{role}') | ||||
|         await self._handle_event(OnGuildRoleCreateABC, role) | ||||
|  | ||||
|     @commands.Cog.listener() | ||||
|     async def on_guild_role_delete(self, role: discord.Role): | ||||
|         self._logger.trace(__name__, f"Received on_guild_role_delete:\n\t{role}") | ||||
|         self._logger.trace(__name__, f'Received on_guild_role_delete:\n\t{role}') | ||||
|         await self._handle_event(OnGuildRoleDeleteABC, role) | ||||
|  | ||||
|     @commands.Cog.listener() | ||||
|     async def on_guild_role_update(self, before: discord.Role, after: discord.Role): | ||||
|         self._logger.trace(__name__, f"Received on_guild_role_update:\n\t{before}\n\t{after}") | ||||
|         self._logger.trace(__name__, f'Received on_guild_role_update:\n\t{before}\n\t{after}') | ||||
|         await self._handle_event(OnGuildRoleUpdateABC, before, after) | ||||
|  | ||||
|     @commands.Cog.listener() | ||||
|     async def on_guild_emojis_update( | ||||
|         self, guild: discord.Guild, before: Sequence[discord.Emoji], after: Sequence[discord.Emoji] | ||||
|     ): | ||||
|         self._logger.trace(__name__, f"Received on_guild_emojis_update:\n\t{guild}\n\t{before}\n\t{after}") | ||||
|     async def on_guild_emojis_update(self, guild: discord.Guild, before: Sequence[discord.Emoji], after: Sequence[discord.Emoji]): | ||||
|         self._logger.trace(__name__, f'Received on_guild_emojis_update:\n\t{guild}\n\t{before}\n\t{after}') | ||||
|         await self._handle_event(OnGuildEmojisUpdateABC, guild, before, after) | ||||
|  | ||||
|     @commands.Cog.listener() | ||||
|     async def on_guild_available(self, guild: discord.Guild): | ||||
|         self._logger.trace(__name__, f"Received on_guild_available:\n\t{guild}") | ||||
|         self._logger.trace(__name__, f'Received on_guild_available:\n\t{guild}') | ||||
|         await self._handle_event(OnGuildAvailableABC, guild) | ||||
|  | ||||
|     @commands.Cog.listener() | ||||
|     async def on_guild_unavailable(self, guild: discord.Guild): | ||||
|         self._logger.trace(__name__, f"Received on_guild_unavailable:\n\t{guild}") | ||||
|         self._logger.trace(__name__, f'Received on_guild_unavailable:\n\t{guild}') | ||||
|         await self._handle_event(OnGuildUnavailableABC, guild) | ||||
|  | ||||
|     @commands.Cog.listener() | ||||
|     async def on_voice_state_update( | ||||
|         self, member: discord.Member, before: discord.VoiceState, after: discord.VoiceState | ||||
|     ): | ||||
|         self._logger.trace(__name__, f"Received on_voice_state_update:\n\t{member}\n\t{before}\n\t{after}") | ||||
|     async def on_scheduled_event_create(self, event: discord.ScheduledEvent): | ||||
|         self._logger.trace(__name__, f'Received on_scheduled_event_create:\n\t{event}') | ||||
|         await self._handle_event(OnScheduledEventCreateABC, event) | ||||
|  | ||||
|     @commands.Cog.listener() | ||||
|     async def on_scheduled_event_delete(self, event: discord.ScheduledEvent): | ||||
|         self._logger.trace(__name__, f'Received on_scheduled_event_delete:\n\t{event}') | ||||
|         await self._handle_event(OnScheduledEventDeleteABC, event) | ||||
|  | ||||
|     @commands.Cog.listener() | ||||
|     async def on_scheduled_event_update(self, before: discord.ScheduledEvent, after: discord.ScheduledEvent): | ||||
|         self._logger.trace(__name__, f'Received on_scheduled_event_update:\n\t{before}, {after}') | ||||
|         await self._handle_event(OnScheduledEventUpdateABC, before, after) | ||||
|  | ||||
|     @commands.Cog.listener() | ||||
|     async def on_scheduled_event_user_add(self, event: discord.ScheduledEvent, user: discord.User): | ||||
|         self._logger.trace(__name__, f'Received on_scheduled_event_user_add:\n\t{event}, {user}') | ||||
|         await self._handle_event(OnScheduledEventUserAddABC, event, user) | ||||
|  | ||||
|     @commands.Cog.listener() | ||||
|     async def on_scheduled_event_user_remove(self, event: discord.ScheduledEvent, user: discord.User): | ||||
|         self._logger.trace(__name__, f'Received on_scheduled_event_user_remove:\n\t{event}, {user}') | ||||
|         await self._handle_event(OnScheduledEventUserRemoveABC, event, user) | ||||
|  | ||||
|     @commands.Cog.listener() | ||||
|     async def on_voice_state_update(self, member: discord.Member, before: discord.VoiceState, after: discord.VoiceState): | ||||
|         self._logger.trace(__name__, f'Received on_voice_state_update:\n\t{member}\n\t{before}\n\t{after}') | ||||
|         await self._handle_event(OnVoiceStateUpdateABC, member, before, after) | ||||
|  | ||||
|     @commands.Cog.listener() | ||||
|     async def on_member_ban(self, guild: discord.Guild, user: discord.User): | ||||
|         self._logger.trace(__name__, f"Received on_member_ban:\n\t{guild}\n\t{user}") | ||||
|         self._logger.trace(__name__, f'Received on_member_ban:\n\t{guild}\n\t{user}') | ||||
|         await self._handle_event(OnMemberBanABC, guild, user) | ||||
|  | ||||
|     @commands.Cog.listener() | ||||
|     async def on_member_unban(self, guild: discord.Guild, user: discord.User): | ||||
|         self._logger.trace(__name__, f"Received on_member_unban:\n\t{guild}\n\t{user}") | ||||
|         self._logger.trace(__name__, f'Received on_member_unban:\n\t{guild}\n\t{user}') | ||||
|         await self._handle_event(OnMemberUnbanABC, guild, user) | ||||
|  | ||||
|     @commands.Cog.listener() | ||||
|     async def on_invite_create(self, invite: discord.Invite): | ||||
|         self._logger.trace(__name__, f"Received on_invite_create:\n\t{invite}") | ||||
|         self._logger.trace(__name__, f'Received on_invite_create:\n\t{invite}') | ||||
|         await self._handle_event(OnInviteCreateABC, invite) | ||||
|  | ||||
|     @commands.Cog.listener() | ||||
|     async def on_invite_delete(self, invite: discord.Invite): | ||||
|         self._logger.trace(__name__, f"Received on_invite_create:\n\t{invite}") | ||||
|         self._logger.trace(__name__, f'Received on_invite_create:\n\t{invite}') | ||||
|         await self._handle_event(OnInviteDeleteABC, invite) | ||||
|  | ||||
|     @commands.Cog.listener() | ||||
|     async def on_group_join(self, channel: discord.GroupChannel, user: discord.User): | ||||
|         self._logger.trace(__name__, f"Received on_group_join:\n\t{channel}\n\t{user}") | ||||
|         self._logger.trace(__name__, f'Received on_group_join:\n\t{channel}\n\t{user}') | ||||
|         await self._handle_event(OnGroupJoinABC, channel, user) | ||||
|  | ||||
|     @commands.Cog.listener() | ||||
|     async def on_group_remove(self, channel: discord.GroupChannel, user: discord.User): | ||||
|         self._logger.trace(__name__, f"Received on_group_remove:\n\t{channel}\n\t{user}") | ||||
|         self._logger.trace(__name__, f'Received on_group_remove:\n\t{channel}\n\t{user}') | ||||
|         await self._handle_event(OnGroupRemoveABC, channel, user) | ||||
|   | ||||
| @@ -2,12 +2,7 @@ from typing import Optional, Callable, Union, Iterable | ||||
|  | ||||
| from cpl_query._helper import is_number | ||||
| from cpl_query.base.sequence import Sequence | ||||
| from cpl_query.exceptions import ( | ||||
|     InvalidTypeException, | ||||
|     ArgumentNoneException, | ||||
|     ExceptionArgument, | ||||
|     IndexOutOfRangeException, | ||||
| ) | ||||
| from cpl_query.exceptions import InvalidTypeException, ArgumentNoneException, ExceptionArgument, IndexOutOfRangeException | ||||
|  | ||||
|  | ||||
| def _default_lambda(x: object) -> object: | ||||
| @@ -15,17 +10,20 @@ def _default_lambda(x: object) -> object: | ||||
|  | ||||
|  | ||||
| class QueryableABC(Sequence): | ||||
|  | ||||
|     def __init__(self, t: type, values: Iterable = None): | ||||
|         Sequence.__init__(self, t, values) | ||||
|  | ||||
|     def all(self, _func: Callable = None) -> bool: | ||||
|         r"""Checks if every element of list equals result found by function | ||||
|  | ||||
|         Parameter: | ||||
|         Parameter | ||||
|         --------- | ||||
|             func: :class:`Callable` | ||||
|                 selected value | ||||
|  | ||||
|         Returns: | ||||
|         Returns | ||||
|         ------- | ||||
|             bool | ||||
|         """ | ||||
|         if _func is None: | ||||
| @@ -36,11 +34,13 @@ class QueryableABC(Sequence): | ||||
|     def any(self, _func: Callable = None) -> bool: | ||||
|         r"""Checks if list contains result found by function | ||||
|  | ||||
|         Parameter: | ||||
|         Parameter | ||||
|         --------- | ||||
|             func: :class:`Callable` | ||||
|                 selected value | ||||
|  | ||||
|         Returns: | ||||
|         Returns | ||||
|         ------- | ||||
|             bool | ||||
|         """ | ||||
|         if _func is None: | ||||
| @@ -51,11 +51,13 @@ class QueryableABC(Sequence): | ||||
|     def average(self, _func: Callable = None) -> Union[int, float, complex]: | ||||
|         r"""Returns average value of list | ||||
|  | ||||
|         Parameter: | ||||
|         Parameter | ||||
|         --------- | ||||
|             func: :class:`Callable` | ||||
|                 selected value | ||||
|  | ||||
|         Returns: | ||||
|         Returns | ||||
|         ------- | ||||
|             Union[int, float, complex] | ||||
|         """ | ||||
|         if _func is None and not is_number(self.type): | ||||
| @@ -66,11 +68,13 @@ class QueryableABC(Sequence): | ||||
|     def contains(self, _value: object) -> bool: | ||||
|         r"""Checks if list contains value given by function | ||||
|  | ||||
|         Parameter: | ||||
|         Parameter | ||||
|         --------- | ||||
|             value: :class:`object` | ||||
|                 value | ||||
|  | ||||
|         Returns: | ||||
|         Returns | ||||
|         ------- | ||||
|             bool | ||||
|         """ | ||||
|         if _value is None: | ||||
| @@ -81,11 +85,13 @@ class QueryableABC(Sequence): | ||||
|     def count(self, _func: Callable = None) -> int: | ||||
|         r"""Returns length of list or count of found elements | ||||
|  | ||||
|         Parameter: | ||||
|         Parameter | ||||
|         --------- | ||||
|             func: :class:`Callable` | ||||
|                 selected value | ||||
|  | ||||
|         Returns: | ||||
|         Returns | ||||
|         ------- | ||||
|             int | ||||
|         """ | ||||
|         if _func is None: | ||||
| @@ -93,14 +99,16 @@ class QueryableABC(Sequence): | ||||
|  | ||||
|         return self.where(_func).count() | ||||
|  | ||||
|     def distinct(self, _func: Callable = None) -> "QueryableABC": | ||||
|     def distinct(self, _func: Callable = None) -> 'QueryableABC': | ||||
|         r"""Returns list without redundancies | ||||
|  | ||||
|         Parameter: | ||||
|         Parameter | ||||
|         --------- | ||||
|             func: :class:`Callable` | ||||
|                 selected value | ||||
|  | ||||
|         Returns: | ||||
|         Returns | ||||
|         ------- | ||||
|             :class: `cpl_query.base.queryable_abc.QueryableABC` | ||||
|         """ | ||||
|         if _func is None: | ||||
| @@ -121,11 +129,13 @@ class QueryableABC(Sequence): | ||||
|     def element_at(self, _index: int) -> any: | ||||
|         r"""Returns element at given index | ||||
|  | ||||
|         Parameter: | ||||
|         Parameter | ||||
|         --------- | ||||
|             _index: :class:`int` | ||||
|                 index | ||||
|  | ||||
|         Returns: | ||||
|         Returns | ||||
|         ------- | ||||
|             Value at _index: any | ||||
|         """ | ||||
|         if _index is None: | ||||
| @@ -143,11 +153,13 @@ class QueryableABC(Sequence): | ||||
|     def element_at_or_default(self, _index: int) -> Optional[any]: | ||||
|         r"""Returns element at given index or None | ||||
|  | ||||
|         Parameter: | ||||
|         Parameter | ||||
|         --------- | ||||
|             _index: :class:`int` | ||||
|                 index | ||||
|  | ||||
|         Returns: | ||||
|         Returns | ||||
|         ------- | ||||
|             Value at _index: Optional[any] | ||||
|         """ | ||||
|         if _index is None: | ||||
| @@ -161,7 +173,8 @@ class QueryableABC(Sequence): | ||||
|     def first(self) -> any: | ||||
|         r"""Returns first element | ||||
|  | ||||
|         Returns: | ||||
|         Returns | ||||
|         ------- | ||||
|             First element of list: any | ||||
|         """ | ||||
|         if self.count() == 0: | ||||
| @@ -172,7 +185,8 @@ class QueryableABC(Sequence): | ||||
|     def first_or_default(self) -> any: | ||||
|         r"""Returns first element or None | ||||
|  | ||||
|         Returns: | ||||
|         Returns | ||||
|         ------- | ||||
|             First element of list: Optional[any] | ||||
|         """ | ||||
|         if self.count() == 0: | ||||
| @@ -183,7 +197,8 @@ class QueryableABC(Sequence): | ||||
|     def for_each(self, _func: Callable = None): | ||||
|         r"""Runs given function for each element of list | ||||
|  | ||||
|         Parameter: | ||||
|         Parameter | ||||
|         --------- | ||||
|             func: :class: `Callable` | ||||
|                 function to call | ||||
|         """ | ||||
| @@ -193,10 +208,11 @@ class QueryableABC(Sequence): | ||||
|  | ||||
|         return self | ||||
|  | ||||
|     def group_by(self, _func: Callable = None) -> "QueryableABC": | ||||
|     def group_by(self, _func: Callable = None) -> 'QueryableABC': | ||||
|         r"""Groups by func | ||||
|  | ||||
|         Returns: | ||||
|         Returns | ||||
|         ------- | ||||
|             Grouped list[list[any]]: any | ||||
|         """ | ||||
|         if _func is None: | ||||
| @@ -219,7 +235,8 @@ class QueryableABC(Sequence): | ||||
|     def last(self) -> any: | ||||
|         r"""Returns last element | ||||
|  | ||||
|         Returns: | ||||
|         Returns | ||||
|         ------- | ||||
|             Last element of list: any | ||||
|         """ | ||||
|         if self.count() == 0: | ||||
| @@ -230,7 +247,8 @@ class QueryableABC(Sequence): | ||||
|     def last_or_default(self) -> any: | ||||
|         r"""Returns last element or None | ||||
|  | ||||
|         Returns: | ||||
|         Returns | ||||
|         ------- | ||||
|             Last element of list: Optional[any] | ||||
|         """ | ||||
|         if self.count() == 0: | ||||
| @@ -241,11 +259,13 @@ class QueryableABC(Sequence): | ||||
|     def max(self, _func: Callable = None) -> object: | ||||
|         r"""Returns the highest value | ||||
|  | ||||
|         Parameter: | ||||
|         Parameter | ||||
|         --------- | ||||
|             func: :class:`Callable` | ||||
|                 selected value | ||||
|  | ||||
|         Returns: | ||||
|         Returns | ||||
|         ------- | ||||
|             object | ||||
|         """ | ||||
|         if _func is None and not is_number(self.type): | ||||
| @@ -259,7 +279,8 @@ class QueryableABC(Sequence): | ||||
|     def median(self, _func=None) -> Union[int, float]: | ||||
|         r"""Return the median value of data elements | ||||
|  | ||||
|         Returns: | ||||
|         Returns | ||||
|         ------- | ||||
|             Union[int, float] | ||||
|         """ | ||||
|         if _func is None: | ||||
| @@ -268,16 +289,22 @@ class QueryableABC(Sequence): | ||||
|         result = self.order_by(_func).select(_func).to_list() | ||||
|         length = len(result) | ||||
|         i = int(length / 2) | ||||
|         return result[i] if length % 2 == 1 else (float(result[i - 1]) + float(result[i])) / float(2) | ||||
|         return ( | ||||
|             result[i] | ||||
|             if length % 2 == 1 | ||||
|             else (float(result[i - 1]) + float(result[i])) / float(2) | ||||
|         ) | ||||
|  | ||||
|     def min(self, _func: Callable = None) -> object: | ||||
|         r"""Returns the lowest value | ||||
|  | ||||
|         Parameter: | ||||
|         Parameter | ||||
|         --------- | ||||
|             func: :class:`Callable` | ||||
|                 selected value | ||||
|  | ||||
|         Returns: | ||||
|         Returns | ||||
|         ------- | ||||
|             object | ||||
|         """ | ||||
|         if _func is None and not is_number(self.type): | ||||
| @@ -288,52 +315,56 @@ class QueryableABC(Sequence): | ||||
|  | ||||
|         return _func(min(self, key=_func)) | ||||
|  | ||||
|     def order_by(self, _func: Callable = None) -> "QueryableABC": | ||||
|     def order_by(self, _func: Callable = None) -> 'OrderedQueryableABC': | ||||
|         r"""Sorts elements by function in ascending order | ||||
|  | ||||
|         Parameter: | ||||
|         Parameter | ||||
|         --------- | ||||
|             func: :class:`Callable` | ||||
|                 selected value | ||||
|  | ||||
|         Returns: | ||||
|             :class: `cpl_query.base.queryable_abc.QueryableABC` | ||||
|         Returns | ||||
|         ------- | ||||
|             :class: `cpl_query.base.ordered_queryable_abc.OrderedQueryableABC` | ||||
|         """ | ||||
|         if _func is None: | ||||
|             _func = _default_lambda | ||||
|  | ||||
|         from cpl_query.base.ordered_queryable import OrderedQueryable | ||||
|  | ||||
|         return OrderedQueryable(self.type, sorted(self, key=_func), _func) | ||||
|  | ||||
|     def order_by_descending(self, _func: Callable = None) -> "QueryableABC": | ||||
|     def order_by_descending(self, _func: Callable = None) -> 'OrderedQueryableABC': | ||||
|         r"""Sorts elements by function in descending order | ||||
|  | ||||
|         Parameter: | ||||
|         Parameter | ||||
|         --------- | ||||
|             func: :class:`Callable` | ||||
|                 selected value | ||||
|  | ||||
|         Returns: | ||||
|             :class: `cpl_query.base.queryable_abc.QueryableABC` | ||||
|         Returns | ||||
|         ------- | ||||
|             :class: `cpl_query.base.ordered_queryable_abc.OrderedQueryableABC` | ||||
|         """ | ||||
|         if _func is None: | ||||
|             _func = _default_lambda | ||||
|  | ||||
|         from cpl_query.base.ordered_queryable import OrderedQueryable | ||||
|  | ||||
|         return OrderedQueryable(self.type, sorted(self, key=_func, reverse=True), _func) | ||||
|  | ||||
|     def reverse(self) -> "QueryableABC": | ||||
|     def reverse(self) -> 'QueryableABC': | ||||
|         r"""Reverses list | ||||
|  | ||||
|         Returns: | ||||
|         Returns | ||||
|         ------- | ||||
|             :class: `cpl_query.base.queryable_abc.QueryableABC` | ||||
|         """ | ||||
|         return type(self)(self._type, reversed(self._values)) | ||||
|  | ||||
|     def select(self, _func: Callable) -> "QueryableABC": | ||||
|     def select(self, _func: Callable) -> 'QueryableABC': | ||||
|         r"""Formats each element of list to a given format | ||||
|  | ||||
|         Returns: | ||||
|         Returns | ||||
|         ------- | ||||
|             :class: `cpl_query.base.queryable_abc.QueryableABC` | ||||
|         """ | ||||
|         if _func is None: | ||||
| @@ -341,10 +372,11 @@ class QueryableABC(Sequence): | ||||
|  | ||||
|         return type(self)(object, [_func(_o) for _o in self]) | ||||
|  | ||||
|     def select_many(self, _func: Callable) -> "QueryableABC": | ||||
|     def select_many(self, _func: Callable) -> 'QueryableABC': | ||||
|         r"""Flattens resulting lists to one | ||||
|  | ||||
|         Returns: | ||||
|         Returns | ||||
|         ------- | ||||
|             :class: `cpl_query.base.queryable_abc.QueryableABC` | ||||
|         """ | ||||
|         # The line below is pain. I don't understand anything of it... | ||||
| @@ -354,41 +386,46 @@ class QueryableABC(Sequence): | ||||
|     def single(self) -> any: | ||||
|         r"""Returns one single element of list | ||||
|  | ||||
|         Returns: | ||||
|         Returns | ||||
|         ------- | ||||
|             Found value: any | ||||
|  | ||||
|         Raises: | ||||
|         Raises | ||||
|         ------ | ||||
|             ArgumentNoneException: when argument is None | ||||
|             Exception: when argument is None or found more than one element | ||||
|         """ | ||||
|         if self.count() > 1: | ||||
|             raise Exception("Found more than one element") | ||||
|             raise Exception('Found more than one element') | ||||
|         elif self.count() == 0: | ||||
|             raise Exception("Found no element") | ||||
|             raise Exception('Found no element') | ||||
|  | ||||
|         return self._values[0] | ||||
|  | ||||
|     def single_or_default(self) -> Optional[any]: | ||||
|         r"""Returns one single element of list | ||||
|  | ||||
|         Returns: | ||||
|         Returns | ||||
|         ------- | ||||
|             Found value: Optional[any] | ||||
|         """ | ||||
|         if self.count() > 1: | ||||
|             raise Exception("Index out of range") | ||||
|             raise Exception('Index out of range') | ||||
|         elif self.count() == 0: | ||||
|             return None | ||||
|  | ||||
|         return self._values[0] | ||||
|  | ||||
|     def skip(self, _index: int) -> "QueryableABC": | ||||
|     def skip(self, _index: int) -> 'QueryableABC': | ||||
|         r"""Skips all elements from index | ||||
|  | ||||
|         Parameter: | ||||
|         Parameter | ||||
|         --------- | ||||
|             _index: :class:`int` | ||||
|                 index | ||||
|  | ||||
|         Returns: | ||||
|         Returns | ||||
|         ------- | ||||
|             :class: `cpl_query.base.queryable_abc.QueryableABC` | ||||
|         """ | ||||
|         if _index is None: | ||||
| @@ -396,14 +433,16 @@ class QueryableABC(Sequence): | ||||
|  | ||||
|         return type(self)(self.type, self._values[_index:]) | ||||
|  | ||||
|     def skip_last(self, _index: int) -> "QueryableABC": | ||||
|     def skip_last(self, _index: int) -> 'QueryableABC': | ||||
|         r"""Skips all elements after index | ||||
|  | ||||
|         Parameter: | ||||
|         Parameter | ||||
|         --------- | ||||
|             _index: :class:`int` | ||||
|                 index | ||||
|  | ||||
|         Returns: | ||||
|         Returns | ||||
|         ------- | ||||
|             :class: `cpl_query.base.queryable_abc.QueryableABC` | ||||
|         """ | ||||
|         if _index is None: | ||||
| @@ -415,11 +454,13 @@ class QueryableABC(Sequence): | ||||
|     def sum(self, _func: Callable = None) -> Union[int, float, complex]: | ||||
|         r"""Sum of all values | ||||
|  | ||||
|         Parameter: | ||||
|         Parameter | ||||
|         --------- | ||||
|             func: :class:`Callable` | ||||
|                 selected value | ||||
|  | ||||
|         Returns: | ||||
|         Returns | ||||
|         ------- | ||||
|             Union[int, float, complex] | ||||
|         """ | ||||
|         if _func is None and not is_number(self.type): | ||||
| @@ -434,15 +475,17 @@ class QueryableABC(Sequence): | ||||
|  | ||||
|         return result | ||||
|  | ||||
|     def split(self, _func: Callable) -> "QueryableABC": | ||||
|     def split(self, _func: Callable) -> 'QueryableABC': | ||||
|         r"""Splits the list by given function | ||||
|  | ||||
|  | ||||
|         Parameter: | ||||
|         Parameter | ||||
|         --------- | ||||
|             func: :class:`Callable` | ||||
|                 seperator | ||||
|  | ||||
|         Returns: | ||||
|         Returns | ||||
|         ------- | ||||
|             :class: `cpl_query.base.queryable_abc.QueryableABC` | ||||
|         """ | ||||
|         groups = [] | ||||
| @@ -465,14 +508,16 @@ class QueryableABC(Sequence): | ||||
|  | ||||
|         return type(self)(self._type, query_groups) | ||||
|  | ||||
|     def take(self, _index: int) -> "QueryableABC": | ||||
|     def take(self, _index: int) -> 'QueryableABC': | ||||
|         r"""Takes all elements from index | ||||
|  | ||||
|         Parameter: | ||||
|         Parameter | ||||
|         --------- | ||||
|             _index: :class:`int` | ||||
|                 index | ||||
|  | ||||
|         Returns: | ||||
|         Returns | ||||
|         ------- | ||||
|             :class: `cpl_query.base.queryable_abc.QueryableABC` | ||||
|         """ | ||||
|         if _index is None: | ||||
| @@ -480,14 +525,16 @@ class QueryableABC(Sequence): | ||||
|  | ||||
|         return type(self)(self._type, self._values[:_index]) | ||||
|  | ||||
|     def take_last(self, _index: int) -> "QueryableABC": | ||||
|     def take_last(self, _index: int) -> 'QueryableABC': | ||||
|         r"""Takes all elements after index | ||||
|  | ||||
|         Parameter: | ||||
|         Parameter | ||||
|         --------- | ||||
|             _index: :class:`int` | ||||
|                 index | ||||
|  | ||||
|         Returns: | ||||
|         Returns | ||||
|         ------- | ||||
|             :class: `cpl_query.base.queryable_abc.QueryableABC` | ||||
|         """ | ||||
|         index = self.count() - _index | ||||
| @@ -497,14 +544,16 @@ class QueryableABC(Sequence): | ||||
|  | ||||
|         return type(self)(self._type, self._values[index:]) | ||||
|  | ||||
|     def where(self, _func: Callable = None) -> "QueryableABC": | ||||
|     def where(self, _func: Callable = None) -> 'QueryableABC': | ||||
|         r"""Select element by function | ||||
|  | ||||
|         Parameter: | ||||
|         Parameter | ||||
|         --------- | ||||
|             func: :class:`Callable` | ||||
|                 selected value | ||||
|  | ||||
|         Returns: | ||||
|         Returns | ||||
|         ------- | ||||
|             :class: `cpl_query.base.queryable_abc.QueryableABC` | ||||
|         """ | ||||
|         if _func is None: | ||||
|   | ||||
		Reference in New Issue
	
	Block a user