# -*- coding: utf-8 -*-
from setuptools import setup

package_dir = \
{'': 'src'}

packages = \
['selva',
 'selva.di',
 'selva.di.service',
 'selva.utils',
 'selva.web',
 'selva.web.middleware',
 'selva.web.request',
 'selva.web.response',
 'selva.web.routing']

package_data = \
{'': ['*']}

install_requires = \
['asgikit>=0.1.2,<0.2.0']

extras_require = \
{':python_version < "3.11"': ['tomli>=2.0.0,<3.0.0']}

setup_kwargs = {
    'name': 'selva',
    'version': '0.1.0',
    'description': 'ASGI Web Framework with Dependency Injection',
    'long_description': '# Project Selva\n\nSelva is a Python ASGI web framework built on top of [asgikit](https://github.com/livioribeiro/asgikit)\nand inspired by Spring Boot, AspNet Core and FastAPI.\n\n## Usage\n\nCreate an application and controller\n\n```python\nfrom selva.web import Application, controller, get\n\n\n@controller\nclass Controller:\n    @get\n    def hello(self):\n        return "Hello, World!"\n\n\napp = Application(Controller)\n```\n\nAdd a service\n\n```python\nfrom selva.di import service\nfrom selva.web import Application, controller, get\n\n\n@service\nclass Greeter:\n    def greet(self, name: str) -> str:\n        return f"Hello, {name}!"\n\n\n@controller\nclass Controller:\n    def __init__(self, greeter: Greeter):\n        self.greeter = greeter\n\n    @get\n    def hello(self):\n        return self.greeter.greet("World")\n\n\napp = Application(Greeter, Controller)\n```\n\nGet parameters from path\n\n```python\nfrom selva.di import service\nfrom selva.web import Application, controller, get\n\n\n@service\nclass Greeter:\n    def greet(self, name: str) -> str:\n        return f"Hello, {name}!"\n\n\n@controller\nclass Controller:\n    def __init__(self, greeter: Greeter):\n        self.greeter = greeter\n\n    @get("hello/{name}")\n    def hello(self, name: str):\n        greeting = self.greeter.greet(name)\n        # A json response will be created from the returned dict\n        return {"greeting": greeting}\n\n\napp = Application(Greeter, Controller)\n```\n\nConfigurations with [Pydantic](https://pydantic-docs.helpmanual.io/usage/settings/)\n\n```python\nfrom selva.di import service\nfrom selva.web import Application, RequestContext, controller, get\nfrom pydantic import BaseSettings\n\n\nclass Settings(BaseSettings):\n    DEFAULT_NAME = "World"\n\n\n@service\ndef settings_factory() -> Settings:\n    return Settings()\n\n\n@service\nclass Greeter:\n    def __init__(self, settings: Settings):\n        self.default_name = settings.DEFAULT_NAME\n\n    def greet(self, name: str | None) -> str:\n        name = name or self.default_name\n        return f"Hello, {name}!"\n\n\n@controller\nclass Controller:\n    def __init__(self, greeter: Greeter):\n        self.greeter = greeter\n\n    @get("hello/{name}")\n    def hello(self, name: str):\n        greeting = self.greeter.greet(name)\n        return {"greeting": greeting}\n\n    @get("hello")\n    def hello_optional(self, context: RequestContext):\n        name = context.query.get("name")\n        greeting = self.greeter.greet(name)\n        return {"greeting": greeting}\n\n\napp = Application(Greeter, Controller)\n```\n\nManage services lifecycle (e.g [Databases](https://www.encode.io/databases/))\n\n```python\nfrom selva.di import service, initializer, finalizer\nfrom selva.web import Application, RequestContext, controller, get\nfrom pydantic import BaseSettings, PostgresDsn\nfrom databases import Database\n\n\nclass Settings(BaseSettings):\n    DEFAULT_NAME = "World"\n    DATABASE_URL: PostgresDsn\n\n\n@service\ndef settings_factory() -> Settings:\n    return Settings()\n\n\n@service\nclass Repository:\n    def __init__(self, settings: Settings):\n        self.database = Database(settings.DATABASE_URL)\n\n    async def get_greeting(self, name: str) -> str:\n        result = await self.database.fetch_one(\n            query="select text from greeting where name = :name",\n            values={"name": name}\n        )\n\n        return result.text\n\n    @initializer\n    async def initialize(self):\n        await self.database.connect()\n        print("Database connection opened")\n\n    @finalizer\n    async def finalize(self):\n        await self.database.disconnect()\n        print("Database connection closed")\n\n\n@service\nclass Greeter:\n    def __init__(self, repository: Repository, settings: Settings):\n        self.repository = repository\n        self.default_name = settings.DEFAULT_NAME\n\n    async def greet(self, name: str | None) -> str:\n        name = name or self.default_name\n        return await self.repository.get_greeting(name)\n\n\n@controller\nclass Controller:\n    def __init__(self, greeter: Greeter):\n        self.greeter = greeter\n\n    @get("hello/{name}")\n    def hello(self, name: str):\n        greeting = self.greeter.greet(name)\n        return {"greeting": greeting}\n\n    @get("hello")\n    def hello_optional(self, context: RequestContext):\n        name = context.query.get("name")\n        greeting = self.greeter.greet(name)\n        return {"greeting": greeting}\n\n\napp = Application(settings_factory, Repository, Greeter, Controller)\n```\n\nDefine controllers and services in a separate module\n\n```\n├───application\n│   ├───controllers.py\n│   ├───repository.py\n│   ├───services.py\n│   └───settings.py\n└───main.py\n```\n\n```python\n### application/settings.py\nfrom selva.di import service\nfrom pydantic import BaseSettings, PostgresDsn\n\n\nclass Settings(BaseSettings):\n    DEFAULT_NAME = "World"\n    DATABASE_URL: PostgresDsn\n\n\n@service\ndef settings_factory() -> Settings:\n    return Settings()\n```\n\n```python\n### application/repository.py\nfrom selva.di import service, initializer, finalizer\nfrom databases import Database\nfrom .settings import Settings\n\n@service\nclass Repository:\n    def __init__(self, settings: Settings):\n        self.database = Database(settings.DATABASE_URL)\n\n    async def get_greeting(self, name: str) -> str:\n        result = await self.database.fetch_one(\n            query="select text from greeting where name = :name",\n            values={"name": name}\n        )\n\n        return result.text\n\n    @initializer\n    async def initialize(self):\n        await self.database.connect()\n        print("Database connection opened")\n\n    @finalizer\n    async def finalize(self):\n        await self.database.disconnect()\n        print("Database connection closed")\n```\n\n```python\n### application/services.py\nfrom selva.di import service\nfrom .settings import Settings\nfrom .repository import Repository\n\n\n@service\nclass Greeter:\n    def __init__(self, repository: Repository, settings: Settings):\n        self.repository = repository\n        self.default_name = settings.DEFAULT_NAME\n\n    async def greet(self, name: str | None) -> str:\n        name = name or self.default_name\n        return await self.repository.get_greeting(name)\n```\n\n```python\n### application/controllers.py\nfrom selva.web import RequestContext, controller, get\nfrom .services import Greeter\n\n@controller\nclass Controller:\n    def __init__(self, greeter: Greeter):\n        self.greeter = greeter\n\n    @get("hello/{name}")\n    def hello(self, name: str):\n        greeting = self.greeter.greet(name)\n        return {"greeting": greeting}\n\n    @get("hello")\n    def hello_optional(self, context: RequestContext):\n        name = context.query.get("name")\n        greeting = self.greeter.greet(name)\n        return {"greeting": greeting}\n```\n\n```python\n### main.py\nfrom selva.web import Application\n\n\n# module named "application" is automatically registered\napp = Application()\n```\n\nWebsockets\n\n```python\nfrom pathlib import Path\nfrom selva.web import Application, FileResponse, RequestContext, controller, get, websocket\nfrom selva.web.errors import WebSocketDisconnectError\n\n@controller\nclass WebSocketController:\n    @get\n    def index(self) -> FileResponse:\n        return FileResponse(Path(__file__).parent / "index.html")\n\n    @websocket("/chat")\n    async def chat(self, context: RequestContext):\n        client = context.websocket\n\n        await client.accept()\n        print(f"[open] Client connected")\n\n        self.handler.clients.append(client)\n\n        while True:\n            try:\n                message = await client.receive()\n                print(f"[message] {message}")\n                await client.send_text(message)\n            except WebSocketDisconnectError:\n                print("[close] Client disconnected")\n                break\n\n\napp = Application(WebSocketController)\n```\n\n```html\n<!DOCTYPE html>\n<html lang="en">\n<head>\n    <meta charset="UTF-8">\n    <title>WebSocket chat</title>\n</head>\n<body>\n<form id="chat-form">\n    <textarea name="message-list" id="message-list" cols="30" rows="10" readonly></textarea>\n    <p>\n        <input type="text" name="message-box" id="message-box" />\n        <button type="submit">Send</button>\n    </p>\n</form>\n\n<script>\n    const messages = [];\n\n    const chat = document.getElementById("chat-form");\n    const textarea = document.getElementById("message-list");\n    textarea.value = "";\n    const messageInput = document.getElementById("message-box");\n\n    const socket = new WebSocket("ws://localhost:8000/chat");\n\n    function addMessage(message) {\n        messages.push(message)\n        textarea.value = `${messages.join("\\n")}`;\n        textarea.scrollTop = textarea.scrollHeight;\n    }\n\n    chat.onsubmit = (event) => {\n        event.preventDefault();\n        const message = messageInput.value;\n        socket.send(message);\n        messageInput.value = "";\n    };\n\n    socket.onopen = (event) => {\n        console.log("[open] Client connected");\n    };\n\n    socket.onmessage = (event) => {\n        const message = event.data;\n        console.log(`[message] "${message}"`)\n        addMessage(message);\n    };\n\n    socket.onclose = (event) => {\n        if (event.wasClean) {\n            console.log(`[close] Connection closed cleanly, code=${event.code} reason=${event.reason}`);\n        } else {\n            console.log(\'[close] Connection died\');\n        }\n    };\n\n    socket.onerror = function(error) {\n        console.log(`[error] ${error.message}`);\n    };\n</script>\n</body>\n</html>\n```\n',
    'author': 'Livio Ribeiro',
    'author_email': 'livioribeiro@outlook.com',
    'maintainer': None,
    'maintainer_email': None,
    'url': 'https://github.com/livioribeiro/selva',
    'package_dir': package_dir,
    'packages': packages,
    'package_data': package_data,
    'install_requires': install_requires,
    'extras_require': extras_require,
    'python_requires': '>=3.10,<4.0',
}


setup(**setup_kwargs)
