Skip to content

Commit

Permalink
Add support for Esmerald (#907)
Browse files Browse the repository at this point in the history
* Add support for Esmerald

* Add missing self to Esmerald routes

* Adding missing Esmerald reference command

* Update piccolo/apps/asgi/commands/templates/app/home/_esmerald_endpoints.py.jinja

Co-authored-by: sinisaos <[email protected]>

* Update piccolo/apps/asgi/commands/templates/app/_esmerald_app.py.jinja

Co-authored-by: sinisaos <[email protected]>

* Remove piccolo admin from esmerald routes

* Add esmerald to template

* Update _esmerald_app.py.jinja with cleat paths

* Update piccolo/apps/asgi/commands/templates/app/_esmerald_app.py.jinja

Co-authored-by: sinisaos <[email protected]>

---------

Co-authored-by: sinisaos <[email protected]>
  • Loading branch information
tarsil and sinisaos authored Dec 12, 2023
1 parent 8580fb7 commit 4fb169d
Show file tree
Hide file tree
Showing 8 changed files with 136 additions and 7 deletions.
4 changes: 2 additions & 2 deletions docs/src/index.rst
Original file line number Diff line number Diff line change
Expand Up @@ -59,8 +59,8 @@ Give me an ASGI web app!
piccolo asgi new
FastAPI, Starlette, BlackSheep, and Litestar are currently supported, with more
coming soon.
FastAPI, Starlette, BlackSheep, Litestar and Esmerald are currently supported,
with more coming soon.

-------------------------------------------------------------------------------

Expand Down
8 changes: 4 additions & 4 deletions docs/src/piccolo/asgi/index.rst
Original file line number Diff line number Diff line change
Expand Up @@ -21,8 +21,8 @@ Routing frameworks
******************

Currently, `Starlette <https://www.starlette.io/>`_, `FastAPI <https://fastapi.tiangolo.com/>`_,
`BlackSheep <https://www.neoteroi.dev/blacksheep/>`_, and
`Litestar <https://litestar.dev/>`_ are supported.
`BlackSheep <https://www.neoteroi.dev/blacksheep/>`_,
`Litestar <https://litestar.dev/>`_ and `Esmerald <https://esmerald.dev/>`_ are supported.

Other great ASGI routing frameworks exist, and may be supported in the future
(`Quart <https://pgjones.gitlab.io/quart/>`_ ,
Expand All @@ -32,8 +32,8 @@ Other great ASGI routing frameworks exist, and may be supported in the future
Which to use?
=============

All are great choices. FastAPI is built on top of Starlette, so they're
very similar. FastAPI and BlackSheep are great if you want to document a REST
All are great choices. FastAPI and Esmerald are built on top of Starlette, so they're
very similar. FastAPI, BlackSheep and Esmerald are great if you want to document a REST
API, as they have built-in OpenAPI support.

-------------------------------------------------------------------------------
Expand Down
2 changes: 1 addition & 1 deletion piccolo/apps/asgi/commands/new.py
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@

TEMPLATE_DIR = os.path.join(os.path.dirname(__file__), "templates/app/")
SERVERS = ["uvicorn", "Hypercorn"]
ROUTERS = ["starlette", "fastapi", "blacksheep", "litestar"]
ROUTERS = ["starlette", "fastapi", "blacksheep", "litestar", "esmerald"]
ROUTER_DEPENDENCIES = {
"fastapi": ["fastapi>=0.100.0"],
}
Expand Down
100 changes: 100 additions & 0 deletions piccolo/apps/asgi/commands/templates/app/_esmerald_app.py.jinja
Original file line number Diff line number Diff line change
@@ -0,0 +1,100 @@
import typing as t

from pathlib import Path

from piccolo.utils.pydantic import create_pydantic_model
from piccolo.engine import engine_finder

from esmerald import (
Esmerald,
Include,
Gateway,
JSONResponse,
APIView,
get,
post,
put,
delete
)
from esmerald.config import StaticFilesConfig

from home.endpoints import home
from home.piccolo_app import APP_CONFIG
from home.tables import Task


async def open_database_connection_pool():
try:
engine = engine_finder()
await engine.start_connection_pool()
except Exception:
print("Unable to connect to the database")


async def close_database_connection_pool():
try:
engine = engine_finder()
await engine.close_connection_pool()
except Exception:
print("Unable to connect to the database")


TaskModelIn: t.Any = create_pydantic_model(
table=Task,
model_name='TaskModelIn'
)
TaskModelOut: t.Any = create_pydantic_model(
table=Task,
include_default_columns=True,
model_name='TaskModelOut'
)


class TaskAPIView(APIView):
path: str = "/"
tags: str = ["Task"]

@get("/")
async def tasks(self) -> t.List[TaskModelOut]:
return await Task.select().order_by(Task.id)


@post('/')
async def create_task(self, payload: TaskModelIn) -> TaskModelOut:
task = Task(**payload.dict())
await task.save()
return task.to_dict()


@put('/{task_id}')
async def update_task(self, payload: TaskModelIn, task_id: int) -> TaskModelOut:
task = await Task.objects().get(Task.id == task_id)
if not task:
return JSONResponse({}, status_code=404)

for key, value in payload.dict().items():
setattr(task, key, value)

await task.save()

return task.to_dict()


@delete('/{task_id}')
async def delete_task(self, task_id: int) -> None:
task = await Task.objects().get(Task.id == task_id)
if not task:
return JSONResponse({}, status_code=404)

await task.remove()


app = Esmerald(
routes=[
Gateway("/", handler=home),
Gateway("/tasks", handler=TaskAPIView)
],
static_files_config=StaticFilesConfig(path="/static", directory=Path("static")),
on_startup=[open_database_connection_pool],
on_shutdown=[close_database_connection_pool],
)
2 changes: 2 additions & 0 deletions piccolo/apps/asgi/commands/templates/app/app.py.jinja
Original file line number Diff line number Diff line change
Expand Up @@ -6,4 +6,6 @@
{% include '_blacksheep_app.py.jinja' %}
{% elif router == 'litestar' %}
{% include '_litestar_app.py.jinja' %}
{% elif router == 'esmerald' %}
{% include '_esmerald_app.py.jinja' %}
{% endif %}
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
import os

import jinja2
from esmerald import Request, Response, get
from esmerald.responses import HTMLResponse

ENVIRONMENT = jinja2.Environment(
loader=jinja2.FileSystemLoader(
searchpath=os.path.join(os.path.dirname(__file__), "templates")
)
)


@get(path="/", include_in_schema=False)
def home(request: Request) -> HTMLResponse:
template = ENVIRONMENT.get_template("home.html.jinja")

content = template.render(title="Piccolo + ASGI",)

return HTMLResponse(content)
Original file line number Diff line number Diff line change
Expand Up @@ -4,4 +4,6 @@
{% include '_blacksheep_endpoints.py.jinja' %}
{% elif router == 'litestar' %}
{% include '_litestar_endpoints.py.jinja' %}
{% elif router == 'esmerald' %}
{% include '_esmerald_endpoints.py.jinja' %}
{% endif %}
Original file line number Diff line number Diff line change
Expand Up @@ -56,6 +56,11 @@
<li><a href="/admin/">Admin</a></li>
<li><a href="/schema/swagger">Swagger API</a></li>
</ul>
<h3>Esmerald</h3>
<ul>
<li><a href="/admin/">Admin</a></li>
<li><a href="/docs/swagger">Swagger API</a></li>
</ul>
</section>
</div>
{% endblock content %}

0 comments on commit 4fb169d

Please sign in to comment.