Skip to content
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

D1 env access #5

Open
wanghaisheng opened this issue May 2, 2024 · 1 comment
Open

D1 env access #5

wanghaisheng opened this issue May 2, 2024 · 1 comment

Comments

@wanghaisheng
Copy link

from fastapi import FastAPI, Request
from pydantic import BaseModel

from js import Response


async def on_fetch(request, env):
    import asgi

    # print("here", env)
    return await asgi.fetch(app, request, env)


app = FastAPI()


@app.get("/")
async def root():
    return {"message": "Hello, World!"}


@app.get("/env")
async def root(req: Request):
    env = req.scope["env"]
    return {
        "message": "Here is an example of getting an environment variable: "
        + env.MESSAGE
    }


class Item(BaseModel):
    name: str
    description: str | None = None
    price: float
    tax: float | None = None


@app.post("/items/")
async def create_item(item: Item):
    return item


@app.put("/items/{item_id}")
async def create_item(item_id: int, item: Item, q: str | None = None):
    result = {"item_id": item_id, **item.dict()}
    if q:
        result.update({"q": q})
    return result


@app.get("/items/{item_id}")
async def read_item(item_id: int):
    return {"item_id": item_id}


@app.get("/tablelist")
async def fetch_tables(req: Request):
    env = req.scope["env"]

    # Query D1 - we'll list all tables in our database in this example
    results = await env.DB.prepare("PRAGMA table_list").all()
    # Return a JSON response
    return Response.json(results)

name = "hello-fastapi"
main = "src/worker.py"
compatibility_flags = ["python_workers"]
compatibility_date = "2023-12-18"

[vars]
MESSAGE = "This is an environment variable"


[[d1_databases]]
binding = "DB" # This will be how you refer to your database in your Worker
database_name = "jsonbase"
database_id = "69cf8448-d541-4bba-80ff-1264e73ccbde"

error

PythonError: Traceback (most recent call last):                                                                              
                                                                                                                                       
    File "/lib/python3.12/site-packages/fastapi/encoders.py", line 322, in jsonable_encoder                                            
      data = dict(obj)
             ^^^^^^^^^
  TypeError: 'pyodide.ffi.JsProxy' object is not iterable

  During handling of the above exception, another exception occurred:

  Traceback (most recent call last):
    File "/lib/python3.12/site-packages/fastapi/encoders.py", line 327, in jsonable_encoder
      data = vars(obj)
             ^^^^^^^^^
  TypeError: vars() argument must have __dict__ attribute

  The above exception was the direct cause of the following exception:

  Traceback (most recent call last):
    File "/session/metadata/worker.py", line 12, in on_fetch
      return await asgi.fetch(app, request, env)
             ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
    File "/lib/python3.12/site-packages/asgi.py", line 188, in fetch
      result = await process_request(app, req, env)
               ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
    File "/lib/python3.12/site-packages/asgi.py", line 130, in process_request
      await app(request_to_scope(req, env), receive, send)
    File "/lib/python3.12/site-packages/fastapi/applications.py", line 1054, in __call__
      await super().__call__(scope, receive, send)
    File "/lib/python3.12/site-packages/starlette/applications.py", line 123, in __call__
      await self.middleware_stack(scope, receive, send)
    File "/lib/python3.12/site-packages/starlette/middleware/errors.py", line 186, in __call__
      raise exc
    File "/lib/python3.12/site-packages/starlette/middleware/errors.py", line 164, in __call__
      await self.app(scope, receive, _send)
    File "/lib/python3.12/site-packages/starlette/middleware/exceptions.py", line 62, in __call__
      await wrap_app_handling_exceptions(self.app, conn)(scope, receive, send)
    File "/lib/python3.12/site-packages/starlette/_exception_handler.py", line 64, in wrapped_app
      raise exc
    File "/lib/python3.12/site-packages/starlette/_exception_handler.py", line 53, in wrapped_app
      await app(scope, receive, sender)
    File "/lib/python3.12/site-packages/starlette/routing.py", line 758, in __call__
      await self.middleware_stack(scope, receive, send)
    File "/lib/python3.12/site-packages/starlette/routing.py", line 778, in app
      await route.handle(scope, receive, send)
    File "/lib/python3.12/site-packages/starlette/routing.py", line 299, in handle
      await self.app(scope, receive, send)
    File "/lib/python3.12/site-packages/starlette/routing.py", line 79, in app
      await wrap_app_handling_exceptions(app, request)(scope, receive, send)
    File "/lib/python3.12/site-packages/starlette/_exception_handler.py", line 64, in wrapped_app
      raise exc
    File "/lib/python3.12/site-packages/starlette/_exception_handler.py", line 53, in wrapped_app
      await app(scope, receive, sender)
    File "/lib/python3.12/site-packages/starlette/routing.py", line 74, in app
      response = await func(request)
                 ^^^^^^^^^^^^^^^^^^^
    File "/lib/python3.12/site-packages/fastapi/routing.py", line 296, in app
      content = await serialize_response(


X [ERROR] ^^^^^^^^^^^^^^^^^^^^^^^^^                                                                                                    
                                                                                                                                       
    File "/lib/python3.12/site-packages/fastapi/routing.py", line 180, in serialize_response                                           
      return jsonable_encoder(response_content)
             ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
    File "/lib/python3.12/site-packages/fastapi/encoders.py", line 330, in jsonable_encoder
      raise ValueError(errors) from e
  ValueError: [TypeError("'pyodide.ffi.JsProxy' object is not iterable"), TypeError('vars() argument
  must have __dict__ attribute')]

      at new_error (pyodide-internal:generated/pyodide.asm:20:9998)
      at [object Object]x16c818
      at [object Object]x17437e
      at _PyEM_TrampolineCall_JS (pyodide-internal:generated/pyodide.asm:20:120091)
      at [object Object]x1bf539
      at [object Object]x2c1c2d
      at [object Object]x206dd5
      at [object Object]x1bfc1b
      at [object Object]x1bff2a
      at [object Object]x1bffa8
      at [object Object]x29a879
      at [object Object]x2a0fde
@maxtheman
Copy link

@wanghaisheng I have run into this a few times now, it's a pyodide thing where the behavior isn't 100% intuitive.

For even somewhat complex dicts, JsProxy often fails to convert to JS without a more explicit instruction. In this case, I recommend using console.log from js import console to introspect the js object and then follow the to_js example in this doc to see how to provide more explicit object converters: https://developers.cloudflare.com/workers/languages/python/examples/

 to_js converts between Python dictionaries and JavaScript Objects
def to_js(obj):
   return _to_js(obj, dict_converter=Object.fromEntries)

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

No branches or pull requests

2 participants