diff --git a/src/cpl_cli/.cpl/schematic_schematic.py b/src/cpl_cli/.cpl/schematic_schematic.py index c5f7ddf0..3570a969 100644 --- a/src/cpl_cli/.cpl/schematic_schematic.py +++ b/src/cpl_cli/.cpl/schematic_schematic.py @@ -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): diff --git a/src/cpl_core/dependency_injection/service_provider.py b/src/cpl_core/dependency_injection/service_provider.py index 8355885e..0be8f567 100644 --- a/src/cpl_core/dependency_injection/service_provider.py +++ b/src/cpl_core/dependency_injection/service_provider.py @@ -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])) diff --git a/src/cpl_core/dependency_injection/service_provider_abc.py b/src/cpl_core/dependency_injection/service_provider_abc.py index f11c3050..5013a670 100644 --- a/src/cpl_core/dependency_injection/service_provider_abc.py +++ b/src/cpl_core/dependency_injection/service_provider_abc.py @@ -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 diff --git a/src/cpl_discord/.cpl/schematic_discord_event.py b/src/cpl_discord/.cpl/schematic_discord_event.py index a5b8f967..d3c2387b 100644 --- a/src/cpl_discord/.cpl/schematic_discord_event.py +++ b/src/cpl_discord/.cpl/schematic_discord_event.py @@ -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', + [] + ) diff --git a/src/cpl_discord/discord_event_types_enum.py b/src/cpl_discord/discord_event_types_enum.py index c8069eab..9d306cb7 100644 --- a/src/cpl_discord/discord_event_types_enum.py +++ b/src/cpl_discord/discord_event_types_enum.py @@ -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 diff --git a/src/cpl_discord/events/on_scheduled_event_create_abc.py b/src/cpl_discord/events/on_scheduled_event_create_abc.py new file mode 100644 index 00000000..a83a6e33 --- /dev/null +++ b/src/cpl_discord/events/on_scheduled_event_create_abc.py @@ -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 diff --git a/src/cpl_discord/events/on_scheduled_event_delete_abc.py b/src/cpl_discord/events/on_scheduled_event_delete_abc.py new file mode 100644 index 00000000..afec0ce7 --- /dev/null +++ b/src/cpl_discord/events/on_scheduled_event_delete_abc.py @@ -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 diff --git a/src/cpl_discord/events/on_scheduled_event_update_abc.py b/src/cpl_discord/events/on_scheduled_event_update_abc.py new file mode 100644 index 00000000..b78ba357 --- /dev/null +++ b/src/cpl_discord/events/on_scheduled_event_update_abc.py @@ -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 diff --git a/src/cpl_discord/events/on_scheduled_event_user_add_abc.py b/src/cpl_discord/events/on_scheduled_event_user_add_abc.py new file mode 100644 index 00000000..944ab298 --- /dev/null +++ b/src/cpl_discord/events/on_scheduled_event_user_add_abc.py @@ -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 diff --git a/src/cpl_discord/events/on_scheduled_event_user_remove_abc.py b/src/cpl_discord/events/on_scheduled_event_user_remove_abc.py new file mode 100644 index 00000000..0839207f --- /dev/null +++ b/src/cpl_discord/events/on_scheduled_event_user_remove_abc.py @@ -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 diff --git a/src/cpl_discord/service/discord_bot_service.py b/src/cpl_discord/service/discord_bot_service.py index 23590a06..4c4716d7 100644 --- a/src/cpl_discord/service/discord_bot_service.py +++ b/src/cpl_discord/service/discord_bot_service.py @@ -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() diff --git a/src/cpl_discord/service/discord_bot_service_abc.py b/src/cpl_discord/service/discord_bot_service_abc.py index 01c106f0..399e5a3f 100644 --- a/src/cpl_discord/service/discord_bot_service_abc.py +++ b/src/cpl_discord/service/discord_bot_service_abc.py @@ -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 diff --git a/src/cpl_discord/service/discord_service.py b/src/cpl_discord/service/discord_service.py index a05fb6a7..44c09db6 100644 --- a/src/cpl_discord/service/discord_service.py +++ b/src/cpl_discord/service/discord_service.py @@ -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) diff --git a/src/cpl_query/base/queryable_abc.py b/src/cpl_query/base/queryable_abc.py index 7d5653fe..ca42e3f3 100644 --- a/src/cpl_query/base/queryable_abc.py +++ b/src/cpl_query/base/queryable_abc.py @@ -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: