Skip to content

Lilya Converter

Lilya

Convert web framework codebases into Lilya with deterministic rules, explicit diagnostics, and reproducible reports.

Test Suite Package version Supported Python versions


Documentation: https://lilya-converter.dymmond.com 📚

Source Code: https://github.com/dymmond/lilya-converter 💻

The official supported version is always the latest released.


Installation

pip install lilya-converter

Optional framework extras:

pip install "lilya-converter[fastapi]"
pip install "lilya-converter[flask]"
pip install "lilya-converter[django]"
pip install "lilya-converter[litestar]"
pip install "lilya-converter[starlette]"

Install with all framework extras:

pip install "lilya-converter[fastapi,flask,django,litestar,starlette]"

Start Here

  1. Get Started
  2. First Conversion
  3. Guides
  4. Examples and Outputs
  5. Command Reference
  6. Adding a New Adapter

Framework Support Matrix

Source Key Status Notes
FastAPI fastapi Stable Default source and backwards-compatible CLI behavior
Flask flask Stable Blueprint and route conversion
Django django Stable URLConf conversion and management-command path remapping
Litestar litestar Stable Decorator and route_handlers conversion
Starlette starlette Stable Route/Mount conversion

What You Get

  • Multi-framework adapter architecture.
  • Deterministic conversion output.
  • Rule-level diagnostics and reports.
  • Dry-run and unified diff previews.
  • Verification checks after conversion.

Quick Command Preview

# Analyze
# lilya-converter analyze ./fastapi_project --json
# lilya-converter analyze ./django_project --source django --output ./reports/scan.json

# Convert with preview
# lilya-converter convert ./litestar_project ./lilya_project --source litestar --dry-run --diff

# Persist reports
# lilya-converter convert ./starlette_project ./lilya_project --source starlette --report ./reports/convert.json
# lilya-converter verify ./lilya_project --source django --report ./reports/verify.json

# Mapping introspection
# lilya-converter map rules --source flask
# lilya-converter map applied ./reports/convert.json

Conversion Preview

FastAPI input

from fastapi import APIRouter, FastAPI
from fastapi.responses import ORJSONResponse, PlainTextResponse

app = FastAPI(openapi_url=None)
router = APIRouter()


@router.api_route(
    "/payload",
    methods=["PATCH"],
    response_class=ORJSONResponse,
    response_model=dict,
    responses={404: {"description": "missing"}},
    status_code=201,
)
async def payload():
    return {"value": 1}


@router.trace("/trace", include_in_schema=False)
async def trace_route():
    return PlainTextResponse("trace")


app.include_router(router)

Lilya output

from lilya.apps import Lilya as FastAPI
from lilya.responses import PlainText as PlainTextResponse
from lilya.routing import Router as APIRouter

app = FastAPI(enable_openapi=False)
router = APIRouter()


@router.route("/payload", methods=["PATCH"])
async def payload():
    return {"value": 1}


@router.route("/trace", include_in_schema=False, methods=["TRACE"])
async def trace_route():
    return PlainTextResponse("trace")


app.include(path="", app=router)

Flask input

from flask import Blueprint, Flask

app = Flask(__name__)
api = Blueprint("api", __name__, url_prefix="/api")


@api.route("/items", endpoint="list_items", strict_slashes=False)
def list_items():
    return {"items": []}


app.register_blueprint(api)

Flask Lilya output

from lilya.apps import Lilya as Flask
from lilya.routing import Router as Blueprint

app = Flask()
api = Blueprint()


@api.route('/api/items', name='list_items', methods=['GET'])
def list_items():
    return {'items': []}


app.include(path='/', app=api)

Django URLConf input

from django.urls import include, path

from .views import health

urlpatterns = [
    path("", health, name="health"),
    path("api/", include("api.urls")),
]

Django Lilya output

from lilya.apps import Lilya
from lilya.routing import Include, Path
from .views import health

urlpatterns = [Path('/', health, name='health'), Include(path='/api/', app='api.urls')]
app = Lilya(routes=urlpatterns)

Litestar input

from litestar import Litestar, Router, get


@get("/health")
async def health() -> dict[str, bool]:
    return {"ok": True}


@get("")
async def list_items() -> dict[str, list[str]]:
    return {"items": []}


api = Router(path="/api", route_handlers=[list_items])
app = Litestar(route_handlers=[health, api])

Litestar Lilya output

from lilya.apps import Lilya as Litestar
from lilya.routing import Router, Path, Include


async def health() -> dict[str, bool]:
    return {'ok': True}


async def list_items() -> dict[str, list[str]]:
    return {'items': []}


api = Router(routes=[Path('/', list_items, methods=['GET'])])
app = Litestar(routes=[Path('/health', health, methods=['GET']), Include(path='/api', app=api)])

Starlette input

from starlette.applications import Starlette
from starlette.routing import Mount, Route


async def homepage(request):
    return None


async def users(request):
    return None


api = Starlette(routes=[Route("/users", users)])
routes = [Route("", homepage), Mount("/api", app=api)]
app = Starlette(debug=True, routes=routes)
app.mount("", app=api)
app.add_route("", route=homepage, methods=["GET"])

Starlette Lilya output

from lilya.apps import Lilya as Starlette
from lilya.routing import Include as Mount, Path as Route


async def homepage(request):
    return None


async def users(request):
    return None


api = Starlette(routes=[Route('/users', users)])
routes = [Route('/', homepage), Mount('/api', app=api)]
app = Starlette(debug=True, routes=routes)
app.include(path='/', app=api)
app.add_route(path='/', handler=homepage, methods=['GET'])