Skip to content

Commit

Permalink
feat: document enum parser
Browse files Browse the repository at this point in the history
  • Loading branch information
Sharp-Eyes committed Sep 22, 2024
1 parent e34b8f2 commit 427a4d6
Show file tree
Hide file tree
Showing 3 changed files with 80 additions and 10 deletions.
18 changes: 18 additions & 0 deletions docs/source/api_ref/impl/parser/enum.rst
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
.. currentmodule:: disnake.ext.components.impl

Enum Parser Implementation
==========================

.. automodule:: components.impl.parser.enum


Classes
-------

.. attributetable:: components.impl.parser.enum.EnumParser

.. autoclass:: components.impl.parser.enum.EnumParser
:members:


.. autoclass:: components.impl.parser.enum.FlagParser
3 changes: 2 additions & 1 deletion docs/source/api_ref/impl/parser/index.rst
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ Submodules

base </api_ref/impl/parser/base>
builtins </api_ref/impl/parser/builtins>
channel </api_ref/impl/parser/channel>
datetime </api_ref/impl/parser/datetime>
enum </api_ref/impl/parser/enum>
channel </api_ref/impl/parser/channel>
snowflake </api_ref/impl/parser/snowflake>
69 changes: 60 additions & 9 deletions src/disnake/ext/components/impl/parser/enum.py
Original file line number Diff line number Diff line change
Expand Up @@ -52,32 +52,52 @@ class EnumParser(parser_base.SourcedParser[_EnumT]):
----------
enum_class:
The enum or flag class to use for parsing.
store_by_value:
Whether :meth:`loads` and :meth:`dumps` expect the enum value type or a string.
For enum types where the members are *not* all of the same type, this
*must* be ``False``.
For enum types where all members are integers, this defaults to
``True``, otherwise this defaults to ``False``.
"""

enum_class: typing.Type[_EnumT]
"""The enum or flag class to use for parsing."""
store_by_value: bool
"""Whether :meth:`loads` and :meth:`dumps` expect the enum's value type or a string.
For enum types where the members are *not* all of the same type, this
*must* be ``False``.
"""
value_parser: parser_base.AnyParser
"""The parser responsible for converting to/from the enum type.
If :attr:`store_by_values` is set to ``False``, this is *always* a
:class:`~components.parser.StringParser`.
"""

def __init__(
self,
enum_class: typing.Type[_EnumT],
*,
store_by_value: typing.Optional[bool] = None,
) -> None:
value_type = _get_enum_type(enum_class)

if issubclass(enum_class, disnake.flags.BaseFlags) and store_by_value is False:
msg = (
"Cannot store disnake flags by name, as their members do not have"
" names."
)
raise ValueError(msg)

value_type = _get_enum_type(enum_class)

# If the enum is not of a single type and store_by_value wasn't
# explicitly set or was explicitly set to false, parse by name.
if value_type is None and not store_by_value:
self.store_by_value = False
self.value_type = str
value_type = str

# If the value type could be determined, set it on the parser and
# respect the input for store_by_value-- default to True for integers.
Expand All @@ -87,7 +107,6 @@ def __init__(
if store_by_value is None
else store_by_value
) # fmt: skip
self.value_type = value_type

# If the value type could not be determined but the user explicitly set
# store_by_value to True, raise an exception.
Expand All @@ -100,20 +119,52 @@ def __init__(
raise ValueError(msg)

self.enum_class = enum_class
self.value_parser = parser_base.get_parser(self.value_type)
self.value_parser = parser_base.get_parser(value_type)

async def loads(self, argument: str, *, source: object) -> _EnumT:
"""Load an enum member from a string.
This uses the underlying :attr:`value_parser`.
.. note::
If :attr:`store_by_value` is True, the ``argument`` is expected to
be the value of an enum member; otherwise, the ``argument`` is
expted to be the name.
Parameters
----------
argument:
The value that is to be loaded into a channel.
async def loads(self, argument: str, *, source: object) -> _EnumT: # noqa: D102
# <<docstring inherited from parser_api.Parser>>
This always matches the channel type of the parser.
source:
The source to use for parsing.
If any of the inner parsers are sourced, this is automatically
passed to them.
"""
parsed = await parser_base.try_loads(self.value_parser, argument, source=source)

if self.store_by_value:
return self.enum_class(parsed) # pyright: ignore[reportCallIssue]
else:
return self.enum_class[parsed] # pyright: ignore[reportInvalidTypeArguments]

async def dumps(self, argument: _EnumT) -> str: # noqa: D102
# <<docstring inherited from parser_api.Parser>>
async def dumps(self, argument: _EnumT) -> str:
"""Dump an enum member into a string.
.. note::
If :attr:`store_by_value` is True, this dumps the name of the
enum member passed as ``argument``; otherwise, this dumps its
value.
Parameters
----------
argument:
The value that is to be dumped.
"""
if self.store_by_value:
result = self.value_parser.dumps(argument.value)
else:
Expand Down

0 comments on commit 427a4d6

Please sign in to comment.