Repository: Rapptz/discord.py

Issue:
Comparing VerificationLevel gives unexpected results
### Summary

Comparing VerificationLevel does not work as expected

### Reproduction Steps

1. Tried to compare VerificationLevel 4 with 1
2. Received a different result than expected

### Minimal Reproducible Code

```python
>>> from discord import VerificationLevel
>>> VerificationLevel(4) > VerificationLevel(1) # "extreme" and "low"
False # !
```


### Expected Results

For the comparison to return `True`

### Actual Results

The comparison returned `False`

### Intents

-

### System Information

- Python v3.8.7-final
- discord.py v1.7.3-final
- aiohttp v3.7.3
- system info: Linux 5.10.49-1-MANJARO

### Checklist

- [X] I have searched the open issues for duplicates.
- [X] I have shown the entire traceback, if possible.
- [X] I have removed my token from display, if visible.

### Additional Context

I was about to open a PR to use IntEnum instead but I see it was removed for compatibility with 3.5


Discussion:
> I was about to open a PR to use IntEnum instead but I see it was removed for compatibility with 3.5

Just to confirm on this, all PRs currently are for the 2.0 version of the library; which drops compat for 3.5. This means you'd be able to PR this just fine.
This is a bug since this operation is [documented](https://discordpy.readthedocs.io/en/v1.7.3/api.html#discord.VerificationLevel) to work.

Resolving patch:
diff --git a/discord/enums.py b/discord/enums.py
--- a/discord/enums.py
+++ b/discord/enums.py
@@ -58,13 +58,17 @@
 )
 
 
-def _create_value_cls(name):
+def _create_value_cls(name, comparable):
     cls = namedtuple('_EnumValue_' + name, 'name value')
     cls.__repr__ = lambda self: f'<{name}.{self.name}: {self.value!r}>'
     cls.__str__ = lambda self: f'{name}.{self.name}'
+    if comparable:
+        cls.__le__ = lambda self, other: isinstance(other, self.__class__) and self.value <= other.value
+        cls.__ge__ = lambda self, other: isinstance(other, self.__class__) and self.value >= other.value
+        cls.__lt__ = lambda self, other: isinstance(other, self.__class__) and self.value < other.value
+        cls.__gt__ = lambda self, other: isinstance(other, self.__class__) and self.value > other.value
     return cls
 
-
 def _is_descriptor(obj):
     return hasattr(obj, '__get__') or hasattr(obj, '__set__') or hasattr(obj, '__delete__')
 
@@ -76,12 +80,12 @@ class EnumMeta(type):
         _enum_member_map_: ClassVar[Dict[str, Any]]
         _enum_value_map_: ClassVar[Dict[Any, Any]]
 
-    def __new__(cls, name, bases, attrs):
+    def __new__(cls, name, bases, attrs, *, comparable: bool = False):
         value_mapping = {}
         member_mapping = {}
         member_names = []
 
-        value_cls = _create_value_cls(name)
+        value_cls = _create_value_cls(name, comparable)
         for key, value in list(attrs.items()):
             is_descriptor = _is_descriptor(value)
             if key[0] == '_' and not is_descriptor:
@@ -252,7 +256,7 @@ def __int__(self):
         return self.value
 
 
-class VerificationLevel(Enum):
+class VerificationLevel(Enum, comparable=True):
     none = 0
     low = 1
     medium = 2
@@ -263,7 +267,7 @@ def __str__(self):
         return self.name
 
 
-class ContentFilter(Enum):
+class ContentFilter(Enum, comparable=True):
     disabled = 0
     no_role = 1
     all_members = 2
@@ -296,7 +300,7 @@ def __str__(self):
         return self.name
 
 
-class NotificationLevel(Enum):
+class NotificationLevel(Enum, comparable=True):
     all_messages = 0
     only_mentions = 1
 
@@ -578,7 +582,7 @@ class StagePrivacyLevel(Enum):
     guild_only = 2
 
 
-class NSFWLevel(Enum):
+class NSFWLevel(Enum, comparable=True):
     default = 0
     explicit = 1
     safe = 2


Test patch: