disagreement 0.1.0rc2__tar.gz → 0.1.0rc3__tar.gz

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (143) hide show
  1. disagreement-0.1.0rc3/MANIFEST.in +4 -0
  2. {disagreement-0.1.0rc2/disagreement.egg-info → disagreement-0.1.0rc3}/PKG-INFO +1 -1
  3. {disagreement-0.1.0rc2 → disagreement-0.1.0rc3}/disagreement/__init__.py +8 -4
  4. {disagreement-0.1.0rc2 → disagreement-0.1.0rc3}/disagreement/client.py +0 -4
  5. {disagreement-0.1.0rc2 → disagreement-0.1.0rc3}/disagreement/ext/app_commands/handler.py +25 -12
  6. {disagreement-0.1.0rc2 → disagreement-0.1.0rc3}/disagreement/ext/app_commands/hybrid.py +1 -1
  7. {disagreement-0.1.0rc2 → disagreement-0.1.0rc3}/disagreement/ext/commands/cog.py +15 -6
  8. {disagreement-0.1.0rc2 → disagreement-0.1.0rc3}/disagreement/ext/commands/core.py +20 -10
  9. {disagreement-0.1.0rc2 → disagreement-0.1.0rc3}/disagreement/gateway.py +102 -63
  10. {disagreement-0.1.0rc2 → disagreement-0.1.0rc3}/disagreement/http.py +19 -4
  11. {disagreement-0.1.0rc2 → disagreement-0.1.0rc3}/disagreement/models.py +3 -6
  12. disagreement-0.1.0rc3/disagreement/py.typed +0 -0
  13. {disagreement-0.1.0rc2 → disagreement-0.1.0rc3/disagreement.egg-info}/PKG-INFO +1 -1
  14. {disagreement-0.1.0rc2 → disagreement-0.1.0rc3}/disagreement.egg-info/SOURCES.txt +1 -0
  15. {disagreement-0.1.0rc2 → disagreement-0.1.0rc3}/pyproject.toml +1 -1
  16. disagreement-0.1.0rc2/MANIFEST.in +0 -3
  17. {disagreement-0.1.0rc2 → disagreement-0.1.0rc3}/LICENSE +0 -0
  18. {disagreement-0.1.0rc2 → disagreement-0.1.0rc3}/README.md +0 -0
  19. {disagreement-0.1.0rc2 → disagreement-0.1.0rc3}/disagreement/audio.py +0 -0
  20. {disagreement-0.1.0rc2 → disagreement-0.1.0rc3}/disagreement/cache.py +0 -0
  21. {disagreement-0.1.0rc2 → disagreement-0.1.0rc3}/disagreement/color.py +0 -0
  22. {disagreement-0.1.0rc2 → disagreement-0.1.0rc3}/disagreement/components.py +0 -0
  23. {disagreement-0.1.0rc2 → disagreement-0.1.0rc3}/disagreement/enums.py +0 -0
  24. {disagreement-0.1.0rc2 → disagreement-0.1.0rc3}/disagreement/error_handler.py +0 -0
  25. {disagreement-0.1.0rc2 → disagreement-0.1.0rc3}/disagreement/errors.py +0 -0
  26. {disagreement-0.1.0rc2 → disagreement-0.1.0rc3}/disagreement/event_dispatcher.py +0 -0
  27. {disagreement-0.1.0rc2 → disagreement-0.1.0rc3}/disagreement/ext/__init__.py +0 -0
  28. {disagreement-0.1.0rc2 → disagreement-0.1.0rc3}/disagreement/ext/app_commands/__init__.py +0 -0
  29. {disagreement-0.1.0rc2 → disagreement-0.1.0rc3}/disagreement/ext/app_commands/commands.py +0 -0
  30. {disagreement-0.1.0rc2 → disagreement-0.1.0rc3}/disagreement/ext/app_commands/context.py +0 -0
  31. {disagreement-0.1.0rc2 → disagreement-0.1.0rc3}/disagreement/ext/app_commands/converters.py +0 -0
  32. {disagreement-0.1.0rc2 → disagreement-0.1.0rc3}/disagreement/ext/app_commands/decorators.py +0 -0
  33. {disagreement-0.1.0rc2 → disagreement-0.1.0rc3}/disagreement/ext/commands/__init__.py +0 -0
  34. {disagreement-0.1.0rc2 → disagreement-0.1.0rc3}/disagreement/ext/commands/converters.py +0 -0
  35. {disagreement-0.1.0rc2 → disagreement-0.1.0rc3}/disagreement/ext/commands/decorators.py +0 -0
  36. {disagreement-0.1.0rc2 → disagreement-0.1.0rc3}/disagreement/ext/commands/errors.py +0 -0
  37. {disagreement-0.1.0rc2 → disagreement-0.1.0rc3}/disagreement/ext/commands/help.py +0 -0
  38. {disagreement-0.1.0rc2 → disagreement-0.1.0rc3}/disagreement/ext/commands/view.py +0 -0
  39. {disagreement-0.1.0rc2 → disagreement-0.1.0rc3}/disagreement/ext/loader.py +0 -0
  40. {disagreement-0.1.0rc2 → disagreement-0.1.0rc3}/disagreement/ext/tasks.py +0 -0
  41. {disagreement-0.1.0rc2 → disagreement-0.1.0rc3}/disagreement/hybrid_context.py +0 -0
  42. {disagreement-0.1.0rc2 → disagreement-0.1.0rc3}/disagreement/i18n.py +0 -0
  43. {disagreement-0.1.0rc2 → disagreement-0.1.0rc3}/disagreement/interactions.py +0 -0
  44. {disagreement-0.1.0rc2 → disagreement-0.1.0rc3}/disagreement/logging_config.py +0 -0
  45. {disagreement-0.1.0rc2 → disagreement-0.1.0rc3}/disagreement/oauth.py +0 -0
  46. {disagreement-0.1.0rc2 → disagreement-0.1.0rc3}/disagreement/permissions.py +0 -0
  47. {disagreement-0.1.0rc2 → disagreement-0.1.0rc3}/disagreement/rate_limiter.py +0 -0
  48. {disagreement-0.1.0rc2 → disagreement-0.1.0rc3}/disagreement/shard_manager.py +0 -0
  49. {disagreement-0.1.0rc2 → disagreement-0.1.0rc3}/disagreement/typing.py +0 -0
  50. {disagreement-0.1.0rc2 → disagreement-0.1.0rc3}/disagreement/ui/__init__.py +0 -0
  51. {disagreement-0.1.0rc2 → disagreement-0.1.0rc3}/disagreement/ui/button.py +0 -0
  52. {disagreement-0.1.0rc2 → disagreement-0.1.0rc3}/disagreement/ui/item.py +0 -0
  53. {disagreement-0.1.0rc2 → disagreement-0.1.0rc3}/disagreement/ui/modal.py +0 -0
  54. {disagreement-0.1.0rc2 → disagreement-0.1.0rc3}/disagreement/ui/select.py +0 -0
  55. {disagreement-0.1.0rc2 → disagreement-0.1.0rc3}/disagreement/ui/view.py +0 -0
  56. {disagreement-0.1.0rc2 → disagreement-0.1.0rc3}/disagreement/utils.py +0 -0
  57. {disagreement-0.1.0rc2 → disagreement-0.1.0rc3}/disagreement/voice_client.py +0 -0
  58. {disagreement-0.1.0rc2 → disagreement-0.1.0rc3}/disagreement.egg-info/dependency_links.txt +0 -0
  59. {disagreement-0.1.0rc2 → disagreement-0.1.0rc3}/disagreement.egg-info/requires.txt +0 -0
  60. {disagreement-0.1.0rc2 → disagreement-0.1.0rc3}/disagreement.egg-info/top_level.txt +0 -0
  61. {disagreement-0.1.0rc2 → disagreement-0.1.0rc3}/docs/caching.md +0 -0
  62. {disagreement-0.1.0rc2 → disagreement-0.1.0rc3}/docs/commands.md +0 -0
  63. {disagreement-0.1.0rc2 → disagreement-0.1.0rc3}/docs/context_menus.md +0 -0
  64. {disagreement-0.1.0rc2 → disagreement-0.1.0rc3}/docs/converters.md +0 -0
  65. {disagreement-0.1.0rc2 → disagreement-0.1.0rc3}/docs/events.md +0 -0
  66. {disagreement-0.1.0rc2 → disagreement-0.1.0rc3}/docs/extension_loader.md +0 -0
  67. {disagreement-0.1.0rc2 → disagreement-0.1.0rc3}/docs/gateway.md +0 -0
  68. {disagreement-0.1.0rc2 → disagreement-0.1.0rc3}/docs/i18n.md +0 -0
  69. {disagreement-0.1.0rc2 → disagreement-0.1.0rc3}/docs/message_history.md +0 -0
  70. {disagreement-0.1.0rc2 → disagreement-0.1.0rc3}/docs/oauth2.md +0 -0
  71. {disagreement-0.1.0rc2 → disagreement-0.1.0rc3}/docs/permissions.md +0 -0
  72. {disagreement-0.1.0rc2 → disagreement-0.1.0rc3}/docs/presence.md +0 -0
  73. {disagreement-0.1.0rc2 → disagreement-0.1.0rc3}/docs/reactions.md +0 -0
  74. {disagreement-0.1.0rc2 → disagreement-0.1.0rc3}/docs/sharding.md +0 -0
  75. {disagreement-0.1.0rc2 → disagreement-0.1.0rc3}/docs/slash_commands.md +0 -0
  76. {disagreement-0.1.0rc2 → disagreement-0.1.0rc3}/docs/task_loop.md +0 -0
  77. {disagreement-0.1.0rc2 → disagreement-0.1.0rc3}/docs/typing_indicator.md +0 -0
  78. {disagreement-0.1.0rc2 → disagreement-0.1.0rc3}/docs/using_components.md +0 -0
  79. {disagreement-0.1.0rc2 → disagreement-0.1.0rc3}/docs/voice_client.md +0 -0
  80. {disagreement-0.1.0rc2 → disagreement-0.1.0rc3}/docs/voice_features.md +0 -0
  81. {disagreement-0.1.0rc2 → disagreement-0.1.0rc3}/docs/webhooks.md +0 -0
  82. {disagreement-0.1.0rc2 → disagreement-0.1.0rc3}/examples/basic_bot.py +0 -0
  83. {disagreement-0.1.0rc2 → disagreement-0.1.0rc3}/examples/component_bot.py +0 -0
  84. {disagreement-0.1.0rc2 → disagreement-0.1.0rc3}/examples/context_menus.py +0 -0
  85. {disagreement-0.1.0rc2 → disagreement-0.1.0rc3}/examples/extension_management.py +0 -0
  86. {disagreement-0.1.0rc2 → disagreement-0.1.0rc3}/examples/hybrid_bot.py +0 -0
  87. {disagreement-0.1.0rc2 → disagreement-0.1.0rc3}/examples/message_history.py +0 -0
  88. {disagreement-0.1.0rc2 → disagreement-0.1.0rc3}/examples/modal_command.py +0 -0
  89. {disagreement-0.1.0rc2 → disagreement-0.1.0rc3}/examples/modal_send.py +0 -0
  90. {disagreement-0.1.0rc2 → disagreement-0.1.0rc3}/examples/sample_extension.py +0 -0
  91. {disagreement-0.1.0rc2 → disagreement-0.1.0rc3}/examples/sharded_bot.py +0 -0
  92. {disagreement-0.1.0rc2 → disagreement-0.1.0rc3}/examples/task_loop.py +0 -0
  93. {disagreement-0.1.0rc2 → disagreement-0.1.0rc3}/examples/voice_bot.py +0 -0
  94. {disagreement-0.1.0rc2 → disagreement-0.1.0rc3}/setup.cfg +0 -0
  95. {disagreement-0.1.0rc2 → disagreement-0.1.0rc3}/tests/test_additional_converters.py +0 -0
  96. {disagreement-0.1.0rc2 → disagreement-0.1.0rc3}/tests/test_cache.py +0 -0
  97. {disagreement-0.1.0rc2 → disagreement-0.1.0rc3}/tests/test_channel_permissions.py +0 -0
  98. {disagreement-0.1.0rc2 → disagreement-0.1.0rc3}/tests/test_client_context_manager.py +0 -0
  99. {disagreement-0.1.0rc2 → disagreement-0.1.0rc3}/tests/test_color.py +0 -0
  100. {disagreement-0.1.0rc2 → disagreement-0.1.0rc3}/tests/test_color_acceptance.py +0 -0
  101. {disagreement-0.1.0rc2 → disagreement-0.1.0rc3}/tests/test_command_checks.py +0 -0
  102. {disagreement-0.1.0rc2 → disagreement-0.1.0rc3}/tests/test_components_factory.py +0 -0
  103. {disagreement-0.1.0rc2 → disagreement-0.1.0rc3}/tests/test_context.py +0 -0
  104. {disagreement-0.1.0rc2 → disagreement-0.1.0rc3}/tests/test_context_menus.py +0 -0
  105. {disagreement-0.1.0rc2 → disagreement-0.1.0rc3}/tests/test_converter_registration.py +0 -0
  106. {disagreement-0.1.0rc2 → disagreement-0.1.0rc3}/tests/test_converters.py +0 -0
  107. {disagreement-0.1.0rc2 → disagreement-0.1.0rc3}/tests/test_error_handler.py +0 -0
  108. {disagreement-0.1.0rc2 → disagreement-0.1.0rc3}/tests/test_errors.py +0 -0
  109. {disagreement-0.1.0rc2 → disagreement-0.1.0rc3}/tests/test_event_dispatcher.py +0 -0
  110. {disagreement-0.1.0rc2 → disagreement-0.1.0rc3}/tests/test_event_error_hook.py +0 -0
  111. {disagreement-0.1.0rc2 → disagreement-0.1.0rc3}/tests/test_extension_loader.py +0 -0
  112. {disagreement-0.1.0rc2 → disagreement-0.1.0rc3}/tests/test_gateway_backoff.py +0 -0
  113. {disagreement-0.1.0rc2 → disagreement-0.1.0rc3}/tests/test_gateway_intent.py +0 -0
  114. {disagreement-0.1.0rc2 → disagreement-0.1.0rc3}/tests/test_help_command.py +0 -0
  115. {disagreement-0.1.0rc2 → disagreement-0.1.0rc3}/tests/test_http_rate_limit.py +0 -0
  116. {disagreement-0.1.0rc2 → disagreement-0.1.0rc3}/tests/test_http_reactions.py +0 -0
  117. {disagreement-0.1.0rc2 → disagreement-0.1.0rc3}/tests/test_hybrid_context.py +0 -0
  118. {disagreement-0.1.0rc2 → disagreement-0.1.0rc3}/tests/test_i18n.py +0 -0
  119. {disagreement-0.1.0rc2 → disagreement-0.1.0rc3}/tests/test_interaction.py +0 -0
  120. {disagreement-0.1.0rc2 → disagreement-0.1.0rc3}/tests/test_logging_config.py +0 -0
  121. {disagreement-0.1.0rc2 → disagreement-0.1.0rc3}/tests/test_member.py +0 -0
  122. {disagreement-0.1.0rc2 → disagreement-0.1.0rc3}/tests/test_message_pager.py +0 -0
  123. {disagreement-0.1.0rc2 → disagreement-0.1.0rc3}/tests/test_modal_send.py +0 -0
  124. {disagreement-0.1.0rc2 → disagreement-0.1.0rc3}/tests/test_modals.py +0 -0
  125. {disagreement-0.1.0rc2 → disagreement-0.1.0rc3}/tests/test_oauth.py +0 -0
  126. {disagreement-0.1.0rc2 → disagreement-0.1.0rc3}/tests/test_permissions.py +0 -0
  127. {disagreement-0.1.0rc2 → disagreement-0.1.0rc3}/tests/test_presence_and_typing.py +0 -0
  128. {disagreement-0.1.0rc2 → disagreement-0.1.0rc3}/tests/test_presence_update.py +0 -0
  129. {disagreement-0.1.0rc2 → disagreement-0.1.0rc3}/tests/test_rate_limiter.py +0 -0
  130. {disagreement-0.1.0rc2 → disagreement-0.1.0rc3}/tests/test_reactions.py +0 -0
  131. {disagreement-0.1.0rc2 → disagreement-0.1.0rc3}/tests/test_send_files.py +0 -0
  132. {disagreement-0.1.0rc2 → disagreement-0.1.0rc3}/tests/test_sharding.py +0 -0
  133. {disagreement-0.1.0rc2 → disagreement-0.1.0rc3}/tests/test_slash_contexts.py +0 -0
  134. {disagreement-0.1.0rc2 → disagreement-0.1.0rc3}/tests/test_tasks_extension.py +0 -0
  135. {disagreement-0.1.0rc2 → disagreement-0.1.0rc3}/tests/test_textchannel_history.py +0 -0
  136. {disagreement-0.1.0rc2 → disagreement-0.1.0rc3}/tests/test_textchannel_purge.py +0 -0
  137. {disagreement-0.1.0rc2 → disagreement-0.1.0rc3}/tests/test_typing_indicator.py +0 -0
  138. {disagreement-0.1.0rc2 → disagreement-0.1.0rc3}/tests/test_ui.py +0 -0
  139. {disagreement-0.1.0rc2 → disagreement-0.1.0rc3}/tests/test_utils.py +0 -0
  140. {disagreement-0.1.0rc2 → disagreement-0.1.0rc3}/tests/test_view_layout.py +0 -0
  141. {disagreement-0.1.0rc2 → disagreement-0.1.0rc3}/tests/test_voice_client.py +0 -0
  142. {disagreement-0.1.0rc2 → disagreement-0.1.0rc3}/tests/test_wait_for.py +0 -0
  143. {disagreement-0.1.0rc2 → disagreement-0.1.0rc3}/tests/test_webhooks.py +0 -0
@@ -0,0 +1,4 @@
1
+ graft docs
2
+ graft examples
3
+ include LICENSE
4
+ include disagreement/py.typed
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: disagreement
3
- Version: 0.1.0rc2
3
+ Version: 0.1.0rc3
4
4
  Summary: A Python library for the Discord API.
5
5
  Author-email: Slipstream <me@slipstreamm.dev>
6
6
  License: BSD 3-Clause
@@ -14,7 +14,7 @@ __title__ = "disagreement"
14
14
  __author__ = "Slipstream"
15
15
  __license__ = "BSD 3-Clause License"
16
16
  __copyright__ = "Copyright 2025 Slipstream"
17
- __version__ = "0.1.0rc2"
17
+ __version__ = "0.1.0rc3"
18
18
 
19
19
  from .client import Client, AutoShardedClient
20
20
  from .models import Message, User, Reaction
@@ -35,7 +35,11 @@ from .enums import GatewayIntent, GatewayOpcode # Export enums
35
35
  from .error_handler import setup_global_error_handler
36
36
  from .hybrid_context import HybridContext
37
37
  from .ext import tasks
38
+ from .logging_config import setup_logging
38
39
 
39
- # Set up logging if desired
40
- # import logging
41
- # logging.getLogger(__name__).addHandler(logging.NullHandler())
40
+ import logging
41
+
42
+
43
+ # Configure a default logger if none has been configured yet
44
+ if not logging.getLogger().hasHandlers():
45
+ setup_logging(logging.INFO)
@@ -123,14 +123,10 @@ class Client:
123
123
 
124
124
  self._closed: bool = False
125
125
  self._ready_event: asyncio.Event = asyncio.Event()
126
- self.application_id: Optional[Snowflake] = None # For Application Commands
127
126
  self.user: Optional["User"] = (
128
127
  None # The bot's own user object, populated on READY
129
128
  )
130
129
 
131
- # Initialize AppCommandHandler
132
- self.app_command_handler: AppCommandHandler = AppCommandHandler(client=self)
133
-
134
130
  # Internal Caches
135
131
  self._guilds: Dict[Snowflake, "Guild"] = {}
136
132
  self._channels: Dict[Snowflake, "Channel"] = (
@@ -1,6 +1,7 @@
1
1
  # disagreement/ext/app_commands/handler.py
2
2
 
3
3
  import inspect
4
+ import logging
4
5
  from typing import (
5
6
  TYPE_CHECKING,
6
7
  Dict,
@@ -64,6 +65,9 @@ if not TYPE_CHECKING:
64
65
  Message = Any
65
66
 
66
67
 
68
+ logger = logging.getLogger(__name__)
69
+
70
+
67
71
  class AppCommandHandler:
68
72
  """
69
73
  Manages application command registration, parsing, and dispatching.
@@ -544,7 +548,7 @@ class AppCommandHandler:
544
548
  await command.invoke(ctx, *parsed_args, **parsed_kwargs)
545
549
 
546
550
  except Exception as e:
547
- print(f"Error invoking app command '{command.name}': {e}")
551
+ logger.error("Error invoking app command '%s': %s", command.name, e)
548
552
  await self.dispatch_app_command_error(ctx, e)
549
553
  # else:
550
554
  # # Default error reply if no handler on client
@@ -594,34 +598,43 @@ class AppCommandHandler:
594
598
  payload = cmd_or_group.to_dict()
595
599
  commands_to_sync.append(payload)
596
600
  except AttributeError:
597
- print(
598
- f"Warning: Command or group '{cmd_or_group.name}' does not have a to_dict() method. Skipping."
601
+ logger.warning(
602
+ "Command or group '%s' does not have a to_dict() method. Skipping.",
603
+ cmd_or_group.name,
599
604
  )
600
605
  except Exception as e:
601
- print(
602
- f"Error converting command/group '{cmd_or_group.name}' to dict: {e}. Skipping."
606
+ logger.error(
607
+ "Error converting command/group '%s' to dict: %s. Skipping.",
608
+ cmd_or_group.name,
609
+ e,
603
610
  )
604
611
 
605
612
  if not commands_to_sync:
606
- print(
607
- f"No commands to sync for {'guild ' + str(guild_id) if guild_id else 'global'} scope."
613
+ logger.info(
614
+ "No commands to sync for %s scope.",
615
+ f"guild {guild_id}" if guild_id else "global",
608
616
  )
609
617
  return
610
618
 
611
619
  try:
612
620
  if guild_id:
613
- print(
614
- f"Syncing {len(commands_to_sync)} commands for guild {guild_id}..."
621
+ logger.info(
622
+ "Syncing %s commands for guild %s...",
623
+ len(commands_to_sync),
624
+ guild_id,
615
625
  )
616
626
  await self.client._http.bulk_overwrite_guild_application_commands(
617
627
  application_id, guild_id, commands_to_sync
618
628
  )
619
629
  else:
620
- print(f"Syncing {len(commands_to_sync)} global commands...")
630
+ logger.info(
631
+ "Syncing %s global commands...",
632
+ len(commands_to_sync),
633
+ )
621
634
  await self.client._http.bulk_overwrite_global_application_commands(
622
635
  application_id, commands_to_sync
623
636
  )
624
- print("Command sync successful.")
637
+ logger.info("Command sync successful.")
625
638
  except Exception as e:
626
- print(f"Error syncing application commands: {e}")
639
+ logger.error("Error syncing application commands: %s", e)
627
640
  # Consider re-raising or specific error handling
@@ -58,4 +58,4 @@ class HybridCommand(SlashCommand, PrefixCommand): # Inherit from both
58
58
  # The correct one will be called depending on how the command is dispatched.
59
59
  # The AppCommandHandler will use AppCommand.invoke (via SlashCommand).
60
60
  # The prefix CommandHandler will use PrefixCommand.invoke.
61
- # This seems acceptable.
61
+ # This seems acceptable.
@@ -1,6 +1,7 @@
1
1
  # disagreement/ext/commands/cog.py
2
2
 
3
3
  import inspect
4
+ import logging
4
5
  from typing import TYPE_CHECKING, List, Tuple, Callable, Awaitable, Any, Dict, Union
5
6
 
6
7
  if TYPE_CHECKING:
@@ -16,6 +17,8 @@ else: # pragma: no cover - runtime imports for isinstance checks
16
17
  # EventDispatcher might be needed if cogs register listeners directly
17
18
  # from disagreement.event_dispatcher import EventDispatcher
18
19
 
20
+ logger = logging.getLogger(__name__)
21
+
19
22
 
20
23
  class Cog:
21
24
  """
@@ -59,8 +62,10 @@ class Cog:
59
62
  cmd.cog = self # Assign the cog instance to the command
60
63
  if cmd.name in self._commands:
61
64
  # This should ideally be caught earlier or handled by CommandHandler
62
- print(
63
- f"Warning: Duplicate command name '{cmd.name}' in cog '{self.cog_name}'. Overwriting."
65
+ logger.warning(
66
+ "Duplicate command name '%s' in cog '%s'. Overwriting.",
67
+ cmd.name,
68
+ self.cog_name,
64
69
  )
65
70
  self._commands[cmd.name.lower()] = cmd
66
71
  # Also register aliases
@@ -79,8 +84,10 @@ class Cog:
79
84
  # For AppCommandGroup, its commands will have cog set individually if they are AppCommands
80
85
  self._app_commands_and_groups.append(app_cmd_obj)
81
86
  else:
82
- print(
83
- f"Warning: Member '{member_name}' in cog '{self.cog_name}' has '__app_command_object__' but it's not an AppCommand or AppCommandGroup."
87
+ logger.warning(
88
+ "Member '%s' in cog '%s' has '__app_command_object__' but it's not an AppCommand or AppCommandGroup.",
89
+ member_name,
90
+ self.cog_name,
84
91
  )
85
92
 
86
93
  elif isinstance(member, (AppCommand, AppCommandGroup)):
@@ -92,8 +99,10 @@ class Cog:
92
99
  # This is a method decorated with @commands.Cog.listener or @commands.listener
93
100
  if not inspect.iscoroutinefunction(member):
94
101
  # Decorator should have caught this, but double check
95
- print(
96
- f"Warning: Listener '{member_name}' in cog '{self.cog_name}' is not a coroutine. Skipping."
102
+ logger.warning(
103
+ "Listener '%s' in cog '%s' is not a coroutine. Skipping.",
104
+ member_name,
105
+ self.cog_name,
97
106
  )
98
107
  continue
99
108
 
@@ -3,6 +3,7 @@
3
3
  from __future__ import annotations
4
4
 
5
5
  import asyncio
6
+ import logging
6
7
  import inspect
7
8
  from typing import (
8
9
  TYPE_CHECKING,
@@ -31,6 +32,8 @@ from .errors import (
31
32
  from .converters import run_converters, DEFAULT_CONVERTERS, Converter
32
33
  from disagreement.typing import Typing
33
34
 
35
+ logger = logging.getLogger(__name__)
36
+
34
37
  if TYPE_CHECKING:
35
38
  from .cog import Cog
36
39
  from disagreement.client import Client
@@ -224,8 +227,10 @@ class CommandHandler:
224
227
  self.commands[command.name.lower()] = command
225
228
  for alias in command.aliases:
226
229
  if alias in self.commands:
227
- print(
228
- f"Warning: Alias '{alias}' for command '{command.name}' conflicts with an existing command or alias."
230
+ logger.warning(
231
+ "Alias '%s' for command '%s' conflicts with an existing command or alias.",
232
+ alias,
233
+ command.name,
229
234
  )
230
235
  self.commands[alias.lower()] = command
231
236
 
@@ -241,6 +246,7 @@ class CommandHandler:
241
246
 
242
247
  def add_cog(self, cog_to_add: "Cog") -> None:
243
248
  from .cog import Cog
249
+
244
250
  if not isinstance(cog_to_add, Cog):
245
251
  raise TypeError("Argument must be a subclass of Cog.")
246
252
 
@@ -258,8 +264,9 @@ class CommandHandler:
258
264
  for event_name, callback in cog_to_add.get_listeners():
259
265
  self.client._event_dispatcher.register(event_name.upper(), callback)
260
266
  else:
261
- print(
262
- f"Warning: Client does not have '_event_dispatcher'. Listeners for cog '{cog_to_add.cog_name}' not registered."
267
+ logger.warning(
268
+ "Client does not have '_event_dispatcher'. Listeners for cog '%s' not registered.",
269
+ cog_to_add.cog_name,
263
270
  )
264
271
 
265
272
  if hasattr(cog_to_add, "cog_load") and inspect.iscoroutinefunction(
@@ -267,7 +274,7 @@ class CommandHandler:
267
274
  ):
268
275
  asyncio.create_task(cog_to_add.cog_load())
269
276
 
270
- print(f"Cog '{cog_to_add.cog_name}' added.")
277
+ logger.info("Cog '%s' added.", cog_to_add.cog_name)
271
278
 
272
279
  def remove_cog(self, cog_name: str) -> Optional["Cog"]:
273
280
  cog_to_remove = self.cogs.pop(cog_name, None)
@@ -277,8 +284,11 @@ class CommandHandler:
277
284
 
278
285
  if hasattr(self.client, "_event_dispatcher"):
279
286
  for event_name, callback in cog_to_remove.get_listeners():
280
- print(
281
- f"Note: Listener '{callback.__name__}' for event '{event_name}' from cog '{cog_name}' needs manual unregistration logic in EventDispatcher."
287
+ logger.debug(
288
+ "Listener '%s' for event '%s' from cog '%s' needs manual unregistration logic in EventDispatcher.",
289
+ callback.__name__,
290
+ event_name,
291
+ cog_name,
282
292
  )
283
293
 
284
294
  if hasattr(cog_to_remove, "cog_unload") and inspect.iscoroutinefunction(
@@ -287,7 +297,7 @@ class CommandHandler:
287
297
  asyncio.create_task(cog_to_remove.cog_unload())
288
298
 
289
299
  cog_to_remove._eject()
290
- print(f"Cog '{cog_name}' removed.")
300
+ logger.info("Cog '%s' removed.", cog_name)
291
301
  return cog_to_remove
292
302
 
293
303
  async def get_prefix(self, message: "Message") -> Union[str, List[str], None]:
@@ -493,11 +503,11 @@ class CommandHandler:
493
503
  ctx.kwargs = parsed_kwargs
494
504
  await command.invoke(ctx, *parsed_args, **parsed_kwargs)
495
505
  except CommandError as e:
496
- print(f"Command error for '{command.name}': {e}")
506
+ logger.error("Command error for '%s': %s", command.name, e)
497
507
  if hasattr(self.client, "on_command_error"):
498
508
  await self.client.on_command_error(ctx, e)
499
509
  except Exception as e:
500
- print(f"Unexpected error invoking command '{command.name}': {e}")
510
+ logger.error("Unexpected error invoking command '%s': %s", command.name, e)
501
511
  exc = CommandInvokeError(e)
502
512
  if hasattr(self.client, "on_command_error"):
503
513
  await self.client.on_command_error(ctx, exc)