Repository: sanic-org/sanic
Pull request: Fix incompatible type annotation of `get` method in the `HTTPMethodView` class
Resolves #2916

Use `getattr` to try getting the `get` handler to avoid the typing annotation incompatibility issue.

Problem statement:
mypy error type for async get function in HTTPMethodView
### Is there an existing issue for this?

- [X] I have searched the existing issues

### Describe the bug

Mypy throws an error overriding the signature of the get method, as it is described only for synchronous execution.

```
error: Signature of "get" incompatible with supertype "HTTPMethodView"  [override]
note:      Superclass:
note:          Callable[..., Any] | None
note:      Subclass:
note:          def get(self, request: Request[Any, Any]) -> Coroutine[Any, Any, HTTPResponse]
```

I suggest changing the description of the get method /sanic/views.py to:

```
get: Union[Callable[..., Any], Coroutine[..., Any], None]
```


### Code snippet

_No response_

### Expected Behavior

_No response_

### How do you run Sanic?

As a script (`app.run` or `Sanic.serve`)

### Operating System

Linux

### Sanic Version

23.12.0

### Additional context

_No response_

Hints from issue discussion:
PR welcome :wink: 
That did not solve the problem for me. `mypy` still complains and I have no idea why.

It works if `None` is removed from the type definition.

```python
 get: Union[Callable[..., Any], Coroutine[..., Any]]
```

I cannot explain this behavior.
@ahopkins 
The problem is here when we are using mypy and try to implement get method
https://github.com/sanic-org/sanic/blob/da1c6465852c8fc0b77ee2618d845665292045e0/sanic/views.py#L118

If there is no handler defined then server is having Attribute error anyways.
Example:
```log
AttributeError: type object 'MyView' has no attribute 'get'
```

Proposed solution:

\- `get: Optional[Callable[..., Any]]`
\+`get: Callable[..., Any]`

* Kindly suggest better solution or if there is a way to implement get in class based view if we are using mypy.

I am going to work on this if nobody else started it or interested in it

Commit message: Remove incompatible type annotation of `get` method in the view class

Patch to review:
diff --git a/sanic/views.py b/sanic/views.py
index bdd48dc4cc..4bdd232ca0 100644
--- a/sanic/views.py
+++ b/sanic/views.py
@@ -115,8 +115,6 @@ def get(self, request: Request):
         to `"/v"`.
     """
 
-    get: Optional[Callable[..., Any]]
-
     decorators: List[Callable[[Callable[..., Any]], Callable[..., Any]]] = []
 
     def __init_subclass__(
@@ -146,9 +144,11 @@ def __init_subclass__(
 
     def dispatch_request(self, request: Request, *args, **kwargs):
         """Dispatch request to appropriate handler method."""
-        handler = getattr(self, request.method.lower(), None)
-        if not handler and request.method == "HEAD":
-            handler = self.get
+        method = request.method.lower()
+        handler = getattr(self, method)
+
+        if not handler and method == "head":
+            handler = getattr(self, "get")
         if not handler:
             # The router will never allow us to get here, but this is
             # included as a fallback and for completeness.


Code review comments:
diff_hunk: @@ -146,9 +144,11 @@ def __init_subclass__(
 
     def dispatch_request(self, request: Request, *args, **kwargs):
         """Dispatch request to appropriate handler method."""
-        handler = getattr(self, request.method.lower(), None)
-        if not handler and request.method == "HEAD":
-            handler = self.get
+        method = request.method.lower()
+        handler = getattr(self, method)
path: sanic/views.py
text: @user1:
```suggestion
        handler = getattr(self, method, None)
```