Skip to content

Refactor handlers to be separate from core logic#170

Merged
jordaneremieff merged 5 commits intoKludex:mainfrom
four43:refactor-split-handlers
Mar 22, 2021
Merged

Refactor handlers to be separate from core logic#170
jordaneremieff merged 5 commits intoKludex:mainfrom
four43:refactor-split-handlers

Conversation

@four43
Copy link
Copy Markdown
Contributor

@four43 four43 commented Mar 20, 2021

Okay here is a BIG one. This refactors out all of the logic for each event source into their own classes. This helps encapsulate all the messy logic for each event source into one place. It also makes it easier to add new event sources as we choose. I namespaced the handlers with "AWS" with thoughts that this could actually apply to other serverless implementations over on Azure, GCP, etc. if needed.

I wanted to get this in front of you sooner rather than later so you could take a look. It needs a couple more lines of coverage and I'm going to go back and look through some of the issues to make sure I have them covered in tests and they're still working (regression is no good)

It might be easier to look at the repo at my commit, not just the changes.

Let me know what you think, big changes like this are scary but it feels a lot cleaner.

@four43 four43 force-pushed the refactor-split-handlers branch from 57c3ce0 to 7a4134e Compare March 20, 2021 14:53
@four43
Copy link
Copy Markdown
Contributor Author

four43 commented Mar 20, 2021

(I'm trying to keep this squashed as best I can, don't mind the force-pushes to my branch)
And mypy ಠ_ಠ picky picky mypy lol

@dltacube
Copy link
Copy Markdown

This looks incredibly organized! Happy to put it through the wringer once it's ready.

@four43
Copy link
Copy Markdown
Contributor Author

four43 commented Mar 20, 2021

Yay they passed!

Please give it a good look over @dltacube! I'm sure there are some weird fringe cases for each of these handlers that isn't spelled out super well in the AWS docs. It would be good to get some E2E tests going for stuff like this, some more real world examples.

Let me know what you think, thanks for taking a look.

@koxudaxi
Copy link
Copy Markdown
Collaborator

@four43
Thank you for creating this issue!!
First, I have a question.
Does your PR treat AWS WebSocket?
#132

My question is related to @jordaneremieff 's comment #163 (comment)

I namespaced the handlers with "AWS" with thoughts that this could actually apply to other serverless implementations over on Azure, GCP, etc. if needed.

I think it's a good first step.
However, We should confirm that the design can support Azure/GCP events.
@jordaneremieff said these requests are not the same structure as AWS. #163 (comment)

@four43
Copy link
Copy Markdown
Contributor Author

four43 commented Mar 20, 2021

I don't think it will handle web sockets right now. I'm very curious about that though. I didn't have an environment set up to test real world concrete examples of it.

I've only used AWS to any real extent. It would be cool to see those other providers. I'd imagine they have a similar event handling pattern, probably different event and context formats however.

Since both of those were open issues, I don't see those as blockers.

Thoughts?

Thanks for your feedback!

@koxudaxi
Copy link
Copy Markdown
Collaborator

I use AWS WebSockets with the old version Mangum.
Currently, the feature is dropped.
I hope the feature is in Mangum or Other libraries.

Since both of those were open issues, I don't see those as blockers.

I think these features are not blockers in your PR directly.
But, We must decide whether Mangum should support these features or out of scope.

@jordaneremieff
What did you think about it?
The theme is very important for the community
We should decide 🤔

@dltacube
Copy link
Copy Markdown

Does this PR have any impact on bringing back websocket support?

@jordaneremieff
Copy link
Copy Markdown
Collaborator

I had a skim, this looks really good. I’ll give it a proper review tomorrow. Great work!

Also, I’ll follow up more about WebSockets/other providers after review, but I think this shouldn’t prevent either from being implemented later. The entrypoint for WebSockets probably could fit well as a handler here since it follows a similar event structure, but other provider events would be trickier. That said, supporting other providers is dropped from the roadmap (at least for now/without more investigation), but supporting WebSockets is something that has just been stalled.

Copy link
Copy Markdown
Collaborator

@jordaneremieff jordaneremieff left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Looks good! I tested against an HTTP API Gateway deployment without issues. Just a few comments, but otherwise I don't see anything that would prevent a merge.

Comment thread .flake8 Outdated
@@ -0,0 +1,2 @@
[flake8]
max-line-length = 120
Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The flake8 configuration is taken care of in setup.cfg, so I don't think we need this. In any case, the max-line-length should be 88.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ah there it is! I was wondering where you got 88 from? It seems old convention was 80 and modern convention is 120 to 150. Why 88?

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I left it at 120 😈 I am curious though, I never know if there is an official source for stuff like this. Conventions and multiple files at once browsing is good. I can comfortably fit 2 120 files on my 2K monitor ¯_(ツ)_/¯

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

88 is the default for python black: https://pypi.org/project/black/

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It is the default for black as dltacube mentioned, and it is also the max line length for this project. I personally find beyond this uncomfortable to read/review, and I think when lines start getting too long it generally indicates something should be refactored (though this is the less important reason).

Please change it back to 88.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Really it's only longer URLs that span the 88 characters. It's brutal to cut everything down so small, lots of weird multiline strings result. I changed it, but it's uglier.

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks. I know it may seem nitpicky or pedantic, but it really does make it much easier for me to review contributions with this line length.

Comment thread mangum/scope.py Outdated


@dataclass
class Scope:
Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

How about making this Event instead of Scope and ScopeDict renamed back to Scope?

Then as_dict would become get_scope (or maybe a new scope property?), and it could be accessed like handler.event.scope or handler.event.get_scope().

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Alternatively, maybe Request instead of Event makes more sense here.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'd like to leave this one scope solely because that's what the ASGI folks call it: https://asgi.readthedocs.io/en/latest/specs/www.html#http-connection-scope

Similarly Event is what AWS calls all of these different lambda triggers. Keeping with existing conventions.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'll move that as_dict() call till later though, might keep things more structured until the very last possible moment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This should be changed from Scope to something else because it actually encompasses more than just the Scope in the class definition - the ScopeDict itself is would be more consistent with the other types (e.g. we don't have ReceiveCallback). So rather than Event or Scope it seems Request would be most appropriate because it contains both the lambda event information and the ASGI request information that ultimately becomes the scope later.

Comment thread mangum/response.py Outdated


@dataclass
class Response:
Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Maybe a new datastructures.py file that combines the classes in response.py and scope.py in a single file.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I re-worked the init files a bit to cleanup imports

@four43
Copy link
Copy Markdown
Contributor Author

four43 commented Mar 21, 2021

There we go I hit some of those cleanup point @jordaneremieff - thanks for looking it over.

Comment thread mangum/__init__.py Outdated
@@ -1 +1,5 @@
from .response import Response
Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Please move Response and Scope to a single file. The reason for doing so isn't for the imports, rather it is easier to maintain a single file with related classes like this.

Copy link
Copy Markdown
Contributor Author

@four43 four43 Mar 21, 2021

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Since I was able to clean up adapter so much, they might fit nicely in adapter... but now circular references.

@four43
Copy link
Copy Markdown
Contributor Author

four43 commented Mar 22, 2021

Alright that should do it. That's gonna be enough bike shedding for me though. Feel free to merge and fiddle with more if you want. I think it's doing the gist of what I wanted it to do.

Comment thread docs/asgi-frameworks.md

@app.route("/")
def endpoint(request: framework.requests.Request) -> dict:
def endpoint(request: Request) -> dict:
Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This would be unchanged because the request in the framework is different than the request used in Mangum itself, though I can change this later after merging.

@four43
Copy link
Copy Markdown
Contributor Author

four43 commented Mar 22, 2021 via email

@jordaneremieff
Copy link
Copy Markdown
Collaborator

Nicely done @four43, I'll merge this is now. :)

@jordaneremieff jordaneremieff merged commit ddf531b into Kludex:main Mar 22, 2021
@four43
Copy link
Copy Markdown
Contributor Author

four43 commented Mar 22, 2021 via email

@tuukkamustonen
Copy link
Copy Markdown

tuukkamustonen commented Mar 22, 2021

@four43 Does this drop log_level parameter from Mangum constructor? I don't see it used anymore, but the docstring is still there? Should the docs reflect that?

@four43
Copy link
Copy Markdown
Contributor Author

four43 commented Mar 22, 2021

@tuukkamustonen - YES! Sorry about that. You'd just use the normal way you configure python loggers.

logging.getLogger('mangum').setLevel(...)

It seemed redundant to provide that functionality in this library. Good call on the docs. We should update those.

@four43 four43 deleted the refactor-split-handlers branch March 22, 2021 15:07
@tuukkamustonen
Copy link
Copy Markdown

It seemed redundant to provide that functionality in this library.

I agree about that. See also #156 for some discussion about the topic.

@tuukkamustonen
Copy link
Copy Markdown

tuukkamustonen commented Mar 22, 2021

@four43 Something else that might bug me is that kwargs are passed around as non-validated dict. When user passes a key, that's not detected or supported by Mangum / chosen handler, wouldn't better approach be to raise an error? kwargs are just dropped by default now (https://github.com/jordaneremieff/mangum/blob/main/mangum/handlers/abstract_handler.py#L17).

four43 added a commit to four43/mangum that referenced this pull request Mar 27, 2021
* Refactor handlers to be separate from core logic

* Cleanup code for black, flake8, pypy

* Cleanup imports

* Move flake8 config to existing setup.cfg

* Updated code style to adhere to 88 char limit
bradsbrown added a commit to bradsbrown/mangum that referenced this pull request Aug 10, 2021
Necessary after Kludex#170
added a `tests/__init__.py` file that lead `find_packages` to treat
`tests`as a package dir, which will clobber `mangum` users' ability
to import from a repo-local `tests` directory.
jordaneremieff pushed a commit that referenced this pull request Aug 11, 2021
Necessary after #170
added a `tests/__init__.py` file that lead `find_packages` to treat
`tests`as a package dir, which will clobber `mangum` users' ability
to import from a repo-local `tests` directory.
four43 added a commit to four43/mangum that referenced this pull request Aug 20, 2021
* Refactor handlers to be separate from core logic

* Cleanup code for black, flake8, pypy

* Cleanup imports

* Move flake8 config to existing setup.cfg

* Updated code style to adhere to 88 char limit
khamaileon pushed a commit to khamaileon/mangum that referenced this pull request Jan 13, 2024
* Refactor handlers to be separate from core logic

* Cleanup code for black, flake8, pypy

* Cleanup imports

* Move flake8 config to existing setup.cfg

* Updated code style to adhere to 88 char limit
khamaileon pushed a commit to khamaileon/mangum that referenced this pull request Jan 13, 2024
Necessary after Kludex#170
added a `tests/__init__.py` file that lead `find_packages` to treat
`tests`as a package dir, which will clobber `mangum` users' ability
to import from a repo-local `tests` directory.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

5 participants