emmett-framework / emmett

The web framework for inventors

Geek Repo:Geek Repo

Github PK Tool:Github PK Tool

Run the readme.md example Error: TypeError: 'granian._granian.RSGIHeaders' object is not subscriptable

RuixiangS opened this issue · comments

commented

It seems like a granian bug, and it works when I use the emmett develop --interface asgi command that works out.
system: Windows 10 Pro 22H2 19045.3086
my_package version list:

absl-py              1.3.0   
anyio                3.7.0   
Appium-Python-Client 2.9.0   
argcomplete          2.1.2   
certifi              2023.5.7
charset-normalizer   3.1.0   
click                8.1.3   
colorama             0.4.6   
colorlog             6.7.0
distlib              0.3.6
emmett               2.5.3
emmett-crypto        0.3.0
emmett-rest          1.5.1
emmett-sentry        0.4.1
exceptiongroup       1.1.1
func-timeout         4.3.5
granian              0.4.2
h11                  0.14.0
idna                 3.4
pendulum             2.1.2
pip                  23.0.1
poium                1.3.2
polars               0.18.2
psycopg2-binary      2.9.6
pyDAL                17.3
pydantic             1.10.8
python-dateutil      2.8.2
python-rapidjson     1.10
pytzdata             2020.1
PyYAML               6.0
renoir               1.6.1
requests             2.31.0
sentry-sdk           1.25.0
setuptools           67.8.0
severus              1.2.1
six                  1.16.0
sniffio              1.3.0
typer                0.9.0
typing_extensions    4.6.3
urllib3              2.0.2
uvicorn              0.19.0
watchfiles           0.19.0
websockets           10.4
wheel                0.38.4

example

from emmett import App, request, response
from emmett.orm import Database, Field, Model
from emmett.tools import requires, service


class Task(Model):
    name = Field.string()
    is_completed = Field.bool(default=False)


app = App(__name__)
app.config.db.uri = "postgres://username:password@localhost/foo"
db = Database(app)
db.define_models(Task)
app.pipeline = [db.pipe]


def is_authenticated():
    print(request.headers)
    return request.headers["Api-Key"] == "foobar"


def not_authorized():
    response.status = 401
    return {"error": "not authorized"}


@app.route(methods="get")
@service.json
@requires(is_authenticated, otherwise=not_authorized)
async def todo():
    page = request.query_params.page or 1
    tasks = Task.where(lambda t: t.is_completed == False).select(paginate=(page, 20))
    return {"tasks": tasks}

My Test

import requests

url = "http://localhost:8000/todo"
headers = {"Api-Key": "foobar"}
response = requests.get(url, headers=headers)

if response.status_code == 200:
    tasks = response.json()["tasks"]
    print(tasks)
else:
    print("Error:", response.status_code, response.json())
commented

Case: Add an additional question when I use emmett develop --interface asgi
I generate a new request whose headers["Api-key"]="not_foobar", otherwise condition will not work properly.
Expected: otherwise return {"error": "not authorized"}

Traceback (most recent call last):
  File "D:\Anaconda\envs\emmett-frame\lib\asyncio\events.py", line 81, in _run
    self._context.run(self._callback, *self._args)
  File "D:\Anaconda\envs\emmett-frame\lib\site-packages\emmett\asgi\handlers.py", line 194, in __call__
    await asyncio.wait_for(
  File "D:\Anaconda\envs\emmett-frame\lib\asyncio\tasks.py", line 455, in wait_for
    return await fut
  File "D:\Anaconda\envs\emmett-frame\lib\site-packages\emmett\http.py", line 112, in asgi
    await self._send_body(send)
  File "D:\Anaconda\envs\emmett-frame\lib\site-packages\emmett\http.py", line 165, in _send_body
    'body': self.encoded_body,
  File "D:\Anaconda\envs\emmett-frame\lib\site-packages\emmett\http.py", line 160, in encoded_body
    return self.body.encode('utf-8')
AttributeError: 'dict' object has no attribute 'encode'

Test

import requests

url = "http://localhost:8000/todo"
headers = {"Api-Key": "not_foobar"}
response = requests.get(url, headers=headers)

if response.status_code == 200:
    tasks = response.json()["tasks"]
    print(tasks)
else:
    print("Error:", response.status_code, response.json())

My bad I didn't check the README example was still valid with 2.5

You can find the updated code in master