Skip to content

Commit

Permalink
Revert raw event consumer system and traits optimization (#442)
Browse files Browse the repository at this point in the history
- Remove unused args from slots
    - Remove unused variables
    - Cleanup code
    - Fix documentation links
  • Loading branch information
davfsa authored Jan 25, 2021
1 parent 4e80aa5 commit 4472654
Show file tree
Hide file tree
Showing 19 changed files with 657 additions and 298 deletions.
2 changes: 1 addition & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@
[![Issues badge](https://img.shields.io/github/issues-raw/hikari-py/hikari)](https://github.com/hikari-py/hikari/issues)
[![This project uses Black](https://img.shields.io/badge/code%20style-black-000000.svg)](https://pypi.org/project/black/)
[![This project uses MyPy](http://www.mypy-lang.org/static/mypy_badge.svg)](https://pypi.org/project/mypy/)
[![Documentation badge](https://img.shields.io/badge/documentation-up-00FF00.svg)](https://hikari-py.github.io/hikari/documentation)
[![Documentation badge](https://img.shields.io/badge/documentation-up-00FF00.svg)](https://hikari-py.github.io/hikari/hikari)

[![discord](https://discord.com/api/guilds/574921006817476608/widget.png?style=banner2)](https://discord.gg/Jx4cNGG)

Expand Down
2 changes: 1 addition & 1 deletion hikari/_about.py
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,7 @@
__copyright__ = "© 2021 davfsa"
__coverage__ = "https://codeclimate.com/github/hikari-py/hikari"
__discord_invite__ = "https://discord.gg/Jx4cNGG"
__docs__ = "https://hikari-py.github.io/hikari/documentation"
__docs__ = "https://hikari-py.github.io/hikari/hikari"
__email__ = "[email protected]"
__issue_tracker__ = "https://github.com/hikari-py/hikari/issues"
__license__ = "MIT"
Expand Down
59 changes: 5 additions & 54 deletions hikari/api/event_manager.py
Original file line number Diff line number Diff line change
Expand Up @@ -54,74 +54,25 @@ class EventManager(abc.ABC):

__slots__: typing.Sequence[str] = ()

@abc.abstractmethod
def add_raw_consumer(self, name: str, consumer: ConsumerT, /) -> None:
"""Register a given async callback to a raw event name.
Parameters
----------
name : str
The case-insensitive name this event should be triggered based on.
consumer : typing.Callable[[gateway_shard.GatewayShard, hikari.internal.data_binding.JSONObject], typing.Coroutine[typing.Any, typing.Any, None]]
The async function to invoke on each raw event. This should take
two positional arguments, the shard that this event is being
triggered by and this raw event's payload.
""" # noqa: E501 - Line too long

@abc.abstractmethod
def get_raw_consumers(self, name: str, /) -> typing.Sequence[ConsumerT]:
"""Get the async callbacks registered for a raw event.
Parameters
----------
name : str
The case-insensitive name of the event to remove a raw consumer for.
Returns
-------
typing.Sequence[typing.Callable[[gateway_shard.GatewayShard, hikari.internal.data_binding.JSONObject], typing.Coroutine[typing.Any, typing.Any, None]]]
A sequence of the found async functions registered for the provided
event name, this will be an empty sequence if no consumers were found.
""" # noqa: E501 - Line too long

@abc.abstractmethod
def remove_raw_consumer(self, name: str, consumer: ConsumerT, /) -> None:
"""Remove a registered async raw event consumer callback.
Parameters
----------
name : str
The case-insensitive name of the event to remove a raw consumer for.
consumer : typing.Callable[[gateway_shard.GatewayShard, hikari.internal.data_binding.JSONObject], typing.Coroutine[typing.Any, typing.Any, None]]
The async function to remove from the registered raw consumers.
Raises
------
LookupError
If the either `name` or `consumer` couldn't be found in the
registered raw consumers.
""" # noqa: E501 - Line too long

@abc.abstractmethod
def consume_raw_event(
self, shard: gateway_shard.GatewayShard, event_name: str, payload: data_binding.JSONObject
self, event_name: str, shard: gateway_shard.GatewayShard, payload: data_binding.JSONObject
) -> None:
"""Consume a raw event.
Parameters
----------
shard : hikari.api.gateway_shard.GatewayShard
Object of the shard that received this event.
event_name : str
The case-insensitive name of the event being triggered.
shard : hikari.api.shard.GatewayShard
Object of the shard that received this event.
payload : hikari.internal.data_binding.JSONObject
Payload of the event being triggered.
Raises
------
LookupError
If no registered raw consumers were found for the provided event
name.
builtins.LookupError
If there is no consumer for the event.
"""

@abc.abstractmethod
Expand Down
18 changes: 13 additions & 5 deletions hikari/event_stream.py
Original file line number Diff line number Diff line change
Expand Up @@ -149,17 +149,25 @@ class EventStream(Streamer[EventT]):
to the streamer.
"""

__slots__ = ("_active", "_app", "_event_type", "_filters", "_queue", "_registered_listener", "_timeout")
__slots__ = (
"_active",
"_event_manager",
"_event_type",
"_filters",
"_queue",
"_registered_listener",
"_timeout",
)

def __init__(
self,
app: traits.BotAware,
app: traits.EventManagerAware,
event_type: typing.Type[EventT],
*,
timeout: typing.Union[float, int, None],
limit: typing.Optional[int] = None,
) -> None:
self._app = app
self._event_manager = app.event_manager
self._active = False
self._event_type = event_type
self._filters: iterators.All[EventT] = iterators.All(())
Expand Down Expand Up @@ -214,7 +222,7 @@ def __del__(self) -> None:
async def close(self) -> None:
if self._active and self._registered_listener is not None:
try:
self._app.event_manager.unsubscribe(self._event_type, self._registered_listener)
self._event_manager.unsubscribe(self._event_type, self._registered_listener)
except ValueError:
pass

Expand Down Expand Up @@ -242,5 +250,5 @@ async def open(self) -> None:
reference = weakref.WeakMethod(self._listener) # type: ignore[arg-type]
listener = _generate_weak_listener(reference)
self._registered_listener = listener
self._app.event_manager.subscribe(self._event_type, listener)
self._event_manager.subscribe(self._event_type, listener)
self._active = True
70 changes: 33 additions & 37 deletions hikari/impl/bot.py
Original file line number Diff line number Diff line change
Expand Up @@ -45,7 +45,6 @@
from hikari import presences
from hikari import traits
from hikari import undefined
from hikari.api import event_manager as event_manager_
from hikari.impl import cache as cache_impl
from hikari.impl import entity_factory as entity_factory_impl
from hikari.impl import event_factory as event_factory_impl
Expand All @@ -65,15 +64,15 @@
from hikari.api import cache as cache_
from hikari.api import entity_factory as entity_factory_
from hikari.api import event_factory as event_factory_
from hikari.api import event_manager as event_manager_
from hikari.api import rest as rest_
from hikari.api import shard as gateway_shard
from hikari.api import voice as voice_
from hikari.internal import data_binding

_LOGGER: typing.Final[logging.Logger] = logging.getLogger("hikari")


class BotApp(traits.BotAware, event_manager_.EventManager):
class BotApp(traits.BotAware):
"""Basic auto-sharding bot implementation.
This is the class you will want to use to start, control, and build a bot
Expand Down Expand Up @@ -213,7 +212,7 @@ class BotApp(traits.BotAware, event_manager_.EventManager):
"_closing_event",
"_closed",
"_entity_factory",
"_events",
"_event_manager",
"_event_factory",
"_executor",
"_http_settings",
Expand Down Expand Up @@ -262,7 +261,7 @@ def __init__(
self._cache = cache_impl.CacheImpl(self, cache_settings)

# Event handling
self._events = event_manager_impl.EventManagerImpl(self, cache=self._cache)
self._event_manager = event_manager_impl.EventManagerImpl(self, cache=self._cache)

# Entity creation
self._entity_factory = entity_factory_impl.EntityFactoryImpl(self)
Expand Down Expand Up @@ -297,7 +296,7 @@ def cache(self) -> cache_.Cache:

@property
def event_manager(self) -> event_manager_.EventManager:
return self._events
return self._event_manager

@property
def entity_factory(self) -> entity_factory_.EntityFactory:
Expand Down Expand Up @@ -354,19 +353,9 @@ def rest(self) -> rest_.RESTClient:
def is_alive(self) -> bool:
return self._is_alive

def add_raw_consumer(self, name: str, consumer: event_manager_.ConsumerT, /) -> None:
self._events.add_raw_consumer(name, consumer)

def get_raw_consumers(self, name: str, /) -> typing.Sequence[event_manager_.ConsumerT]:
return self._events.get_raw_consumers(name)

def remove_raw_consumer(self, name: str, consumer: event_manager_.ConsumerT, /) -> None:
self._events.remove_raw_consumer(name, consumer)

def consume_raw_event(
self, shard: gateway_shard.GatewayShard, event_name: str, payload: data_binding.JSONObject
) -> None:
self._events.consume_raw_event(shard, event_name, payload)
def _check_if_alive(self) -> None:
if not self._is_alive:
raise errors.ComponentNotRunningError("bot is not running so it cannot be interacted with")

async def close(self, force: bool = True) -> None:
"""Kill the application by shutting all components down."""
Expand Down Expand Up @@ -396,7 +385,7 @@ async def handle(name: str, awaitable: typing.Awaitable[typing.Any]) -> None:
}
)

await self.dispatch(self.event_factory.deserialize_stopping_event())
await self._event_manager.dispatch(self._event_factory.deserialize_stopping_event())

_LOGGER.log(ux.TRACE, "StoppingEvent dispatch completed, now beginning termination")

Expand All @@ -417,17 +406,19 @@ async def handle(name: str, awaitable: typing.Awaitable[typing.Any]) -> None:
self._shards.clear()
self._is_alive = False

await self.dispatch(self.event_factory.deserialize_stopped_event())
await self._event_manager.dispatch(self._event_factory.deserialize_stopped_event())

def dispatch(self, event: event_manager_.EventT_inv) -> asyncio.Future[typing.Any]:
return self._events.dispatch(event)
return self._event_manager.dispatch(event)

def get_listeners(
self, event_type: typing.Type[event_manager_.EventT_co], *, polymorphic: bool = True
) -> typing.Collection[event_manager_.CallbackT[event_manager_.EventT_co]]:
return self._events.get_listeners(event_type, polymorphic=polymorphic)
return self._event_manager.get_listeners(event_type, polymorphic=polymorphic)

async def join(self, until_close: bool = True) -> None:
self._check_if_alive()

awaitables: typing.List[typing.Awaitable[typing.Any]] = [s.join() for s in self._shards.values()]
if until_close:
awaitables.append(self._closing_event.wait())
Expand All @@ -437,9 +428,10 @@ async def join(self, until_close: bool = True) -> None:
def listen(
self, event_type: typing.Optional[typing.Type[event_manager_.EventT_co]] = None
) -> typing.Callable[
[event_manager_.CallbackT[event_manager_.EventT_co]], event_manager_.CallbackT[event_manager_.EventT_co]
[event_manager_.CallbackT[event_manager_.EventT_co]],
event_manager_.CallbackT[event_manager_.EventT_co],
]:
return self._events.listen(event_type)
return self._event_manager.listen(event_type)

@staticmethod
def print_banner(banner: typing.Optional[str], allow_color: bool, force_color: bool) -> None:
Expand Down Expand Up @@ -570,7 +562,15 @@ def run(
status : hikari.presences.Status
The initial status to show for the user presence on startup.
Defaults to `hikari.presences.Status.ONLINE`.
Raises
------
builtins.RuntimeError
If bot is already running.
"""
if self._is_alive:
raise RuntimeError("bot is already running")

if shard_ids is not None and shard_count is None:
raise TypeError("'shard_ids' must be passed with 'shard_count'")

Expand Down Expand Up @@ -747,7 +747,7 @@ async def start(
)

requirements_task = asyncio.create_task(self._rest.fetch_gateway_bot(), name="fetch gateway sharding settings")
await self.dispatch(self.event_factory.deserialize_starting_event())
await self._event_manager.dispatch(self._event_factory.deserialize_starting_event())
requirements = await requirements_task

if shard_count is None:
Expand Down Expand Up @@ -838,14 +838,10 @@ async def start(
)
)

await self.dispatch(self.event_factory.deserialize_started_event())
await self._event_manager.dispatch(self._event_factory.deserialize_started_event())

_LOGGER.info("application started successfully in approx %.2f seconds", time.monotonic() - start_time)

def _check_if_alive(self) -> None:
if not self._is_alive:
raise errors.ComponentNotRunningError("bot is not running so it cannot be interacted with")

def stream(
self,
event_type: typing.Type[event_manager_.EventT_co],
Expand All @@ -854,15 +850,15 @@ def stream(
limit: typing.Optional[int] = None,
) -> event_stream.Streamer[event_manager_.EventT_co]:
self._check_if_alive()
return self._events.stream(event_type, timeout=timeout, limit=limit)
return self._event_manager.stream(event_type, timeout=timeout, limit=limit)

def subscribe(
self, event_type: typing.Type[typing.Any], callback: event_manager_.CallbackT[typing.Any]
) -> event_manager_.CallbackT[typing.Any]:
return self._events.subscribe(event_type, callback)
return self._event_manager.subscribe(event_type, callback)

def unsubscribe(self, event_type: typing.Type[typing.Any], callback: event_manager_.CallbackT[typing.Any]) -> None:
self._events.unsubscribe(event_type, callback)
self._event_manager.unsubscribe(event_type, callback)

async def wait_for(
self,
Expand All @@ -872,7 +868,7 @@ async def wait_for(
predicate: typing.Optional[event_manager_.PredicateT[event_manager_.EventT_co]] = None,
) -> event_manager_.EventT_co:
self._check_if_alive()
return await self._events.wait_for(event_type, timeout=timeout, predicate=predicate)
return await self._event_manager.wait_for(event_type, timeout=timeout, predicate=predicate)

async def update_presence(
self,
Expand Down Expand Up @@ -917,8 +913,6 @@ async def _start_one_shard(
url: str,
) -> shard_impl.GatewayShardImpl:
new_shard = shard_impl.GatewayShardImpl(
event_manager=self._events,
event_factory=self._event_factory,
http_settings=self._http_settings,
initial_activity=activity,
initial_is_afk=afk,
Expand All @@ -929,6 +923,8 @@ async def _start_one_shard(
proxy_settings=self._proxy_settings,
shard_id=shard_id,
shard_count=shard_count,
event_manager=self._event_manager,
event_factory=self._event_factory,
token=self._token,
url=url,
)
Expand Down
6 changes: 3 additions & 3 deletions hikari/impl/event_manager.py
Original file line number Diff line number Diff line change
Expand Up @@ -58,7 +58,7 @@ def _fixed_size_nonce() -> str:
class EventManagerImpl(event_manager_base.EventManagerBase):
"""Provides event handling logic for Discord events."""

__slots__: typing.Sequence[str] = ("_cache", "_cache_settings")
__slots__: typing.Sequence[str] = ("_cache",)

def __init__(self, app: traits.BotAware, /, *, cache: typing.Optional[cache_.MutableCache] = None) -> None:
self._cache = cache
Expand Down Expand Up @@ -149,8 +149,8 @@ async def on_guild_create(self, shard: gateway_shard.GatewayShard, payload: data
for voice_state in event.voice_states.values():
self._cache.set_voice_state(voice_state)

members_declared = self._intents & intents_.Intents.GUILD_MEMBERS
presences_declared = self._intents & intents_.Intents.GUILD_PRESENCES
members_declared = self._app.intents & intents_.Intents.GUILD_MEMBERS
presences_declared = self._app.intents & intents_.Intents.GUILD_PRESENCES

# When intents are enabled discord will only send other member objects on the guild create
# payload if presence intents are also declared, so if this isn't the case then we also want
Expand Down
Loading

0 comments on commit 4472654

Please sign in to comment.