Async, simple, fast: pick three! Roll is a pico framework with performances and aesthetic in mind.
Check out the latest documentation for an extended overview of what can and cannot be achieved.
Async, simple, fast: pick three! Roll is a pico framework with performances and aesthetic in mind.
Home Page: http://roll.readthedocs.io/
Async, simple, fast: pick three! Roll is a pico framework with performances and aesthetic in mind.
Check out the latest documentation for an extended overview of what can and cannot be achieved.
Can you create a new release of roll which supports websockets 8.0.2?
I just installed it and in my simple tests, it works, so it might be enough to relax the version constraint to >=7,<9
Hi (hope you're doing great !), and thanks for the project, love it so far :-) I'm trying to find a way to split the views in different python files, but as the views are all relying on the app, I'm not sure how to do it.
In the Flask project, they're using an intermediate concept named Blueprints for this, and I believe what I'm looking for seems similar.
Did you already face this issue? Any idea on how do deal with this? Thanks !
When you use decorators (not using native functools.wrap
or wrapt
lib) before routes, you get the following error:
ValueError: Route with name wrapper already exists: foo.wrapper
Either we document that all decorators must use an explicit way of definition or we force to name every route or something else.
I think it's from 7655d0e
Not sure why we moved the request hook after the dispatching.
Was it to have request.route
set before?
I don't really know if it is a bug or a feature.
I was logging the request parameters using a @app.listen(request)
decorator but at this point the request.body is not loaded yet.
I changed it for @app.listen("response")
Jul 06 05:59:49 slz025 Trefle[26087]: Unhandled exception in event loop
Jul 06 05:59:49 slz025 Trefle[26087]: Traceback (most recent call last):
Jul 06 05:59:49 slz025 Trefle[26087]: File "/srv/trefle/venv/lib/python3.6/site-packages/roll/__init__.py", line 420, in data_received
Jul 06 05:59:49 slz025 Trefle[26087]: self.parser.feed_data(data)
Jul 06 05:59:49 slz025 Trefle[26087]: File "httptools/parser/parser.pyx", line 193, in httptools.parser.parser.HttpParser.feed_data
Jul 06 05:59:49 slz025 Trefle[26087]: httptools.parser.errors.HttpParserInvalidMethodError: invalid HTTP method
Jul 06 05:59:49 slz025 Trefle[26087]: During handling of the above exception, another exception occurred:
Jul 06 05:59:49 slz025 Trefle[26087]: Traceback (most recent call last):
Jul 06 05:59:49 slz025 Trefle[26087]: File "uvloop/handles/stream.pyx", line 784, in uvloop.loop.__uv_stream_on_read_impl
Jul 06 05:59:49 slz025 Trefle[26087]: File "uvloop/handles/stream.pyx", line 563, in uvloop.loop.UVStream._on_read
Jul 06 05:59:49 slz025 Trefle[26087]: File "/srv/trefle/venv/lib/python3.6/site-packages/roll/__init__.py", line 437, in data_received
Jul 06 05:59:49 slz025 Trefle[26087]: self.write()
Jul 06 05:59:49 slz025 Trefle[26087]: File "/srv/trefle/venv/lib/python3.6/site-packages/roll/__init__.py", line 509, in write
Jul 06 05:59:49 slz025 Trefle[26087]: self.request.method in self._BODYLESS_METHODS))
Jul 06 05:59:49 slz025 Trefle[26087]: AttributeError: method
For the record, we have some funny players in the access_logs:
185.222.211.18 - - [06/Jul/2018:19:03:07 +0000] "\x03\x00\x00/*\xE0\x00\x00\x00\x00\x00Cookie: mstshash=Administr" 400 182 "-" "-"
112.66.78.59 - - [06/Jul/2018:23:35:56 +0000] "\x01\x00\x00\x00\x01\x00\x00\x00\x08\x08" 400 182 "-" "-"
46.161.9.31 - - [07/Jul/2018:12:27:08 +0000] "\x05\x01\x00" 400 182 "-" "-"
46.161.9.31 - - [07/Jul/2018:12:30:09 +0000] "\x04\x01\x00P.\xA1\x09\x1F\x00" 400 182 "-" "-"
185.224.134.205 - - [07/Jul/2018:01:59:46 +0000] "SSH-2.0-libssh2_1.7.0" 400 182 "-" "-"
46.165.243.209 - - [07/Jul/2018:03:55:40 +0000] "\x16\x03\x01\x00\xCF\x01\x00\x00\xCB\x03\x03\xB6/\xBFs\x06C\x92\xC9\x8B\x87\xBB\xE1\x0F\xC9\x8F\x9E\x092\x1D\xD5F\xFB\xD1\x06\x93\xC2;L\xBC\xDE\x8F\xDE\x00\x00\x5C\xC0,\xC00\xC0+\xC0/\xCC\xA9\xCC\xA8\x00\xA3\x00\x9F\x00\xA2\x00\x9E\xCC\xAA\xC0\xAF\xC0\xAD\xC0$\xC0(\xC0" 400 182 "-" "-"
123.127.189.9 - - [06/Jul/2018:05:59:50 +0000] "\x16\x03\x01\x02\x00\x01\x00\x01\xFC\x03\x03\x98x#\xBF%\x9A&0\xA2\x056\xE1.$\x09\x03\x88\xCEN\xC5\x84\xDA\xA1\x012P\xD1\x93#\xFE}\xBD\x00\x00\xB2\x00\x05\x00\x04\x00\x02\x00\x01\x00\x16\x003\x009\x00:\x00\x18\x005\x00" 400 182 "-" "-"
123.127.189.9 - - [06/Jul/2018:05:59:56 +0000] "LMTJ / HTTP/1.1" 499 0 "-" "Mozilla/5.0 (compatible; Nmap Scripting Engine; https://nmap.org/book/nse.html)"
123.127.189.9 - - [06/Jul/2018:05:59:57 +0000] "\x16\x03\x01\x02\x00\x01\x00\x01\xFC\x03\x03\xDCk\x14T\xFB\x10\x9D\xFFHd4L\xF8\x7F\xD1\x16\x89\xD2\x9Ee\xA2\xE2\x15\xA3[\x9F\x8B\x03\xBC\x1D\x9B\xAD\x00\x00\xB2\x00\x05\x00\x04\x00\x02\x00\x01\x00\x16\x003\x009\x00:\x00\x18\x005\x00" 400 182 "-" "-"
123.127.189.9 - - [06/Jul/2018:05:59:59 +0000] "\x16\x03\x01\x02\x00\x01\x00\x01\xFC\x03\x03x\xFFZo\xBB\xB2-\x1C\x8C\xF9o\x0B0eUg\xD6\xDD\x8C\xB2*\x98\xE7\x91\x7F\xBB\x1Ee\x83 \xB0z\x00\x00\xB2\x00\x05\x00\x04\x00\x02\x00\x01\x00\x16\x003\x009\x00:\x00\x18\x005\x00" 400 182 "-" "-"
66.240.205.34 - - [05/Jul/2018:08:19:46 +0000] "Gh0st\xAD\x00\x00\x00\xE0\x00\x00\x00x\x9CKS``\x98\xC3\xC0\xC0\xC0\x06\xC4\x8C@\xBCQ\x96\x81\x81\x09H\x07\xA7\x16\x95e&\xA7*\x04$&g+\x182\x94\
xF6\xB000\xAC\xA8rc\x00\x01\x11\xA0\x82\x1F\x5C`&\x83\xC7K7\x86\x19\xE5n\x0C9\x95n\x0C;\x84\x0F3\xAC\xE8sch\xA8^\xCF4'J\x97\xA9\x82\xE30\xC3\x91h]&\x90\xF8\xCE\x97S\xCBA4L?2=\xE1\xC4\x92\x86
\x0B@\xF5`\x0CT\x1F\xAE\xAF]" 400 182 "-" "-"
import inspect
from abc import ABC
class View(ABC):
pass
def view_methods(cls):
members = dict(inspect.getmembers(cls, predicate=inspect.isfunction))
valid_methods = set(members.keys()) & set({'GET', 'POST'})
for key in valid_methods:
yield key, members[key]
class Roll:
...
def view(self, path: str, **payload):
def wrapper(cls):
for meth, handler in view_methods(cls):
payload[meth] = handler
self.routes.add(path, **payload)
return cls
return wrapper
Hi, I was missing a simple helper to create URLs for me (and ensure these URLs are working correclty), so I crafted something for my own usage.
It might be helpful to others, so here is a link for it. It's very fresh so any feedback is appreciated, maybe there are better ways to iterate on the routes, or to do this.
Here is a link : https://github.com/indatwood/copanier/blob/wip/copanier/views/core.py#L93-L115
Building from a specific Linux platform is not supported.
cf pypi/legacy#120
Seems we are including the example
folder in the release, which is then installed as first class package, which we don't want.
We now have a few place where we raise exceptions, we currently only raise built-in exceptions, maybe it's time to have custom ones, easier to catch and understand for Roll users.
cf #136
Similarly to #64 the implementation of 'Access-Control-Allow-Headers': '*'
does not work on Firefox rejecting with a preflight error.
Example sending Access-Control-Request-Headers: authorization
in Firefox:
Cross-Origin Request Blocked: The Same Origin Policy disallows reading the remote resource at http://localhost:3579/user. (Reason: missing token ‘authorization’ in CORS header ‘Access-Control-Allow-Headers’ from CORS preflight channel).[Learn More]
Works as expected on Chromium.
Also works on Firefox when explicitely using cors(app, "*", methods="*", headers=["Authorization"])
instead of headers="*"
Let's have a dedicated "reference" for the testing utils.
Sometimes, you want to define two routes for the same handler, for instance:
@app.route("/url")
@app.route("/old-url")
async def handler():
(Think legacy)
In that case, which route to return with url_for
? Maybe only the named one? Maybe a regular redirection for the old route is the correct way to do?
The changelog documentation states that a changelog should link to related issues… but we don't do it! :p
Hello Pyrates,
I forked Roll yesterday and added websockets capabilities based on the "websockets" async package.
It's working quite well. I had to create "liveserver" to test the websockets requests in "real" conditions, as the mock Transport was causing problems. This creates a dependency on 'aiohttp', to use the http client they have (maybe there are alternatives ?).
Is this something you'd be interested in, for the core of Roll, of should I move it all in an extension package ?
Cheers.
Should we use "https://pypi.org/project/multidict/" as a case insensitive dict to handle our headers ?
As a mere curiosity (rightly so), I ported Roll on Curio and named it "Granite".
https://github.com/trollfot/granite
If you're interested, it may have pointers for the actuall asyncio Roll, maybe to take it down a notch and don't use a Protocol but the sockets directly. This provides much more flexiblity, especially what I did on Granite : not read the body on request reception but rather wait to see if the body is useful to extract it.
This multiline string contains illegal escape sequences:
Line 99 in d253c68
Fix:Use raw string like so:
logger.debug(r'''
Hello,
do you plan to add HTTP/2 support to Roll in the future ?
Which headers should Roll provides and which should be let to the users?
cf #23
Would allow to subclass only Roll and not Protocol for a custom Query for instance.
Dependabot couldn't authenticate with https://pypi.python.org/simple/.
You can provide authentication details in your Dependabot dashboard by clicking into the account menu (in the top right) and selecting 'Config variables'.
On a manually-built release of httptools (git clone https://github.com/1st1/httptools.git
, git submodule update --init
, make compile
, pip install .
), I'm getting this ImportError
.
I was thinking this morning while working on a project that outputs a lot of CSV that that would be very handy if Response would obey to the file API, so one would do something like:
import csv
@app.route('/')
async def my_view(request, response):
writer = csv.writer(response)
writer.writerow(xxxx)
Meaning that at first response.write
call, the Response would send the headers and first chunk, and then stream chunks at each later calls.
I remember we did discuss this some time ago, but can't remember the conclusion, so just put here a reminder to either implement this, or explain it would not be a good idea. :)
A declarative, efficient, and flexible JavaScript library for building user interfaces.
🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
An Open Source Machine Learning Framework for Everyone
The Web framework for perfectionists with deadlines.
A PHP framework for web artisans
Bring data to life with SVG, Canvas and HTML. 📊📈🎉
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
Some thing interesting about web. New door for the world.
A server is a program made to process requests and deliver data to clients.
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
Some thing interesting about visualization, use data art
Some thing interesting about game, make everyone happy.
We are working to build community through open source technology. NB: members must have two-factor auth.
Open source projects and samples from Microsoft.
Google ❤️ Open Source for everyone.
Alibaba Open Source for everyone
Data-Driven Documents codes.
China tencent open source team.