-
-
Notifications
You must be signed in to change notification settings - Fork 2.1k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Allow route registration with decorator #1735
Conversation
@asvetlov @kxepal @popravich @socketpair thoughts? |
router = mock.Mock(spec=MockAbstractRouter) | ||
app = web.Application(router=router) | ||
|
||
@app.route('/index.html') |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
in my own impplementation of such decorator, I add reference to decorated method and all decorator's kwargs and args to some global array. And also I have a function that adds this saved information into application's routes.
In short (pseudocode):
global_array = []
def handler(*args, **kwargs):
def decorator(function):
global_array.append((function, args, kwargs))
return function
return decorator
@handler(....)
async def myhandler(request):
....
class MyApplication(web.Application):
def add_saved_routes(self):
for (method, args, kwargs):
self.add_route(....)
def main():
app = MyApplication()
app.add_saved_routes()
...
This allows me to use decorators BEFORE creating application (during imports). This is especially important since I have many handlers which are placed in many files.
So, could you provide complete example showing usage of your decorators for the case when there are many files with handlers ?
I think this is a bad idea and goes against everything we have now. Routes as decorators forces you to use module-level scope to define application, loop and the rest of bits, returning you to the Yesterday I meet one interesting issue with that kind of design using aiohttp: I investigated a project, where application and uvloop where defined at the module level. This module imported another one just before uvloop was set as the default, where Consul client was created as well at the module level. And since there was no loop argument passed for him, that client picked current default asyncio loop that was available - certainly not the uvloop one, since it was not yet even created. You may guess what happened next, when half of you application works with the one loop and some parts with the else one. And obliviously, author didn't even expected surprises of that kind. I believe decorator routes will only make more situations like this. For current design, I tend to think that Pyramid-style will fits more without much differences. For people who need flask-like style design, there is sanic already. |
agree with @kxepal, there is even FAQ entry about such routing: http://aiohttp.readthedocs.io/en/stable/faq.html#are-there-any-plans-for-app-route-decorator-like-in-flask |
Agree with @kxepal completely. |
Agreed with @kxepal. from .public import session, signature, user
api_resources = {
user: {
'create': ('/users', ['POST'], {}),
'verify': ('/users/verify/<uuid:user_id>/<string:verification_key>',
['PATCH'],
{}),
},
session: {
'create': ('/users/sessions', ['POST'], {}),
'delete': ('/users/sessions', ['DELETE'], {}),
},
signature: {
'verify': ('/signatures/verify', ['HEAD'], {}),
},
} |
sorry for delay. I see two problems we discuss here. I totally agree on configuration as a side effect of import problem, but I find app configuration func could look like: from . import users, content, ...
def build_app():
app = web.Application()
app.add_subapp('/users', users.USERS_APP)
app.add_subapp('/content', content.CONTENT_APP)
...
return app |
820e413
to
34704ba
Compare
added one module usage limitation |
Codecov Report
@@ Coverage Diff @@
## master #1735 +/- ##
==========================================
+ Coverage 97.41% 97.42% +<.01%
==========================================
Files 37 37
Lines 7432 7445 +13
Branches 1288 1290 +2
==========================================
+ Hits 7240 7253 +13
Misses 79 79
Partials 113 113
Continue to review full report at Codecov.
|
I still think this is a bad move. Yes, this feature will allow us to have nice hello-world examples. Yes, this feature will make simple to make single modules web applications as like it was for single page web apps. But. If application will grow and user will be forced to split it into modules he/she will have to rewrite whole the routing system, application initialization and drop global context usage. And all this may not be quite oblivious. So there will be two chairs problem: or stay within a single module forever or cry for help. Even for small applications, decorator-way may not be convenient. I'm working now on service which have only two routes. But, these routes are belongs to different API versions and I don't want to mix them or their logic in a single module because of coupling problem. So they are defined in two different modules, each of those defines how each API version should act. There will be also a problem to use different routers with such kind of design. For instance, aiohttp_traversal. Decorator routes cannot be used with this one by design reasons. |
I think we have here a lot of words against this feature. Is there any good reasons to have it? |
Convenience, that is it, nothing else. I think we think too big, big applications, huge load, big teams. But I have a felling that in reality python get pushed back to area of glue language and data analytics. And most users just need to build something fast with minimal effort. Of course we can say f... them, learn how to write code, but again that is my feeling, those people are our primary audience. And It seems client part of aiohttp is more popular than server, which proves my point of view. |
It is not about replacing normal registration with decorators, it is just adding ergonomics for small apps |
Let's create a small third party library for route decorators, put it into aio-libs and reference from aiohttp documentation. |
I don't like idea of separate repo. this feature is for new developers with prior flask and similar experience. |
I think it is useful, especially combined with sub-applications