Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
25 changes: 25 additions & 0 deletions interactions/api/models/attrs_utils.py
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
from copy import deepcopy
from functools import wraps
from typing import Dict, Mapping, Optional, Tuple

Expand All @@ -18,9 +19,16 @@ class DictSerializerMixin:
_extras: dict = attrs.field(init=False, repr=False)
"""A dict containing values that were not serialized from Discord."""

__deepcopy__ = False
"""Should the kwargs be deepcopied or not?"""

def __init__(self, kwargs_dict: dict = None, /, **other_kwargs):
kwargs = kwargs_dict or other_kwargs
client = kwargs.pop("_client", None)

if self.__deepcopy__:
kwargs = deepcopy(kwargs)

self._json = kwargs.copy()
passed_kwargs = {}

Expand Down Expand Up @@ -169,6 +177,23 @@ def inner_convert_object(value):
return inner_convert_object


def deepcopy_kwargs(cls: Optional[type] = None):
"""
A decorator to make the DictSerializerMixin deepcopy the kwargs before processing them.
This can help avoid weird bugs with some objects, though will error out in others.
"""

def decorator(cls: type):
cls.__deepcopy__ = True # type: ignore
return cls

if cls is not None:
cls.__deepcopy__ = True # type: ignore
return cls

return decorator


define_defaults = dict(kw_only=True, eq=False, init=False, on_setattr=attrs.setters.NO_OP)


Expand Down
8 changes: 8 additions & 0 deletions interactions/api/models/attrs_utils.pyi
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,8 @@ class DictSerializerMixin:
_json: dict = attrs.field(init=False)
_extras: dict = attrs.field(init=False)
"""A dict containing values that were not serialized from Discord."""
__deepcopy__: bool = attrs.field(init=False)
"""Should the kwargs be deepcopied or not?"""
def __init__(self, kwargs_dict: dict = None, /, **other_kwargs): ...

@attrs.define(eq=False, init=False, on_setattr=attrs.setters.NO_OP)
Expand Down Expand Up @@ -63,3 +65,9 @@ def convert_dict(
value_converter: Optional[Callable[[Any], _P]] = None,
) -> Callable[[Dict[Any, Any]], Dict[_T, _P]]:
"""A helper function to convert the keys and values of a dictionary with the specified converters"""

def deepcopy_kwargs(cls: Optional[Type[_T]] = None) -> Callable[[Any], _T]:
"""
A decorator to make the DictSerializerMixin deepcopy the kwargs before processing them.
This can help avoid weird bugs with some objects, though will error out in others.
"""
16 changes: 2 additions & 14 deletions interactions/api/models/message.py
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@
DictSerializerMixin,
convert_list,
convert_type,
deepcopy_kwargs,
define,
field,
)
Expand Down Expand Up @@ -457,6 +458,7 @@ def __setattr__(self, key, value) -> None:


@define()
@deepcopy_kwargs()
class Embed(DictSerializerMixin):
"""
A class object representing an embed.
Expand Down Expand Up @@ -877,20 +879,6 @@ class Message(ClientSerializerMixin):
converter=convert_list(Sticker), default=None
) # deprecated

def __attrs_post_init__(self):
if self.embeds:
# note from astrea49: this dumb fix is necessary to make sure the _json
# is correct when using a dict for the embeds when initializing
# otherwise, attributes like the footer will be missing or incorrect
# i have no idea why this is necessary and i've have tried debugging for hours
# to find why it's necessary, but i've came up with nothing
# by all means, the converters and json should be correct, but it isn't
# this also happens nowhere else as far as i can tell

# this line should NOT be touched unless you somehow find a solution to
# this, or end up modifying how _json works altogether
self._json["embeds"] = [e._json for e in self.embeds]

async def get_channel(self) -> Channel:
"""
Gets the channel where the message was sent.
Expand Down