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

packages = \
['bakery']

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

modules = \
['py']
entry_points = \
{'pytest11': ['bakery_mock = bakery.testbakery']}

setup_kwargs = {
    'name': 'fresh-bakery',
    'version': '0.2.0',
    'description': 'Bake your dependencies stupidly simple!',
    'long_description': '\n<p align="center">\n  <a href="https://fresh-bakery.readthedocs.io/en/latest/"><img width="300px" src="https://user-images.githubusercontent.com/17745407/187294435-a3bc6b26-b7df-43e5-abd3-0d7a7f92b71e.png" alt=\'fresh-bakery\'></a>\n</p>\n<p align="center">\n    <em>🍰 The little DI framework that tastes like a cake. 🍰</em>\n</p>\n\n---\n\n**Documentation**: [https://fresh-bakery.readthedocs.io/en/latest/](https://fresh-bakery.readthedocs.io/en/latest/)\n\n---\n\n# Fresh Bakery\n\nFresh bakery is a lightweight [Dependency Injection][DI] framework/toolkit,\nwhich is ideal for building object dependencies in Python.\n\nIt is [nearly] production-ready, and gives you the following:\n\n* A lightweight, stupidly simple DI framework.\n* Fully asynchronous, no synchronous mode.\n* Any async backends compatible (`asyncio`, `trio`).\n* Zero dependencies.\n* `Mypy` compatible (no probably need for `# type: ignore`).\n* `FastAPI` fully compatible.\n* `Pytest` fully compatible (Fresh Bakery encourages the use of `pytest`).\n* Ease of testing.\n* Easily extended (contribution is welcome).\n\n## Requirements\n\nPython 3.6+\n\n## Installation\n\n```shell\n$ pip3 install fresh-bakery\n```\n\n## Examples\n\n### Raw example\nIn this example, you can see how to create a specific IoC container using the fresh bakery library in plain python code \n```python\nimport asyncio\n\nfrom dataclasses import dataclass\nfrom bakery import Bakery, Cake\n\n\n# your dependecies\n@dataclass\nclass Settings:\n    database_dsn: str\n    info_id_list: list[int]\n\n\nclass Database:\n    def __init__(self, dsn: str):\n        self.dsn: str = dsn\n\n    async def fetch_info(self, info_id: int) -> dict:\n        return {"dsn": self.dsn, "info_id": info_id}\n\n\nclass InfoManager:\n    def __init__(self, database: Database):\n        self.database: Database = database\n\n    async def fetch_full_info(self, info_id: int) -> dict:\n        info: dict = await self.database.fetch_info(info_id)\n        info["full"] = True\n        return info\n\n\n# specific ioc container, all magic happens here\nclass MyBakeryIOC(Bakery):\n    settings: Settings = Cake(Settings, database_dsn="my_dsn", info_id_list=[1,2,3])\n    database: Database = Cake(Database, dsn=settings.database_dsn)\n    manager: InfoManager = Cake(InfoManager, database=database)\n\n\n# code in your application that needs those dependencies ↑\nasync def main() -> None:\n    async with MyBakery() as bakery:\n        for info_id in bakery.settings.info_id_list:\n            info: dict = await bakery.manager.fetch_full_info(info_id)\n            assert info["dsn"] == bakery.settings.database_dsn\n            assert info["info_id"] == info_id\n            assert info["full"]\n\n\n# just a piece of service code\nif __name__ == "__main__":\n    asyncio.run(main())\n```\n\n### FastAPI example\nThis is a full-fledged complex example of how you can use IoC with your FastAPI application:\n```python\nimport asyncio\nimport random\nimport typing\n\nimport bakery\nimport fastapi\nimport pydantic\nfrom loguru import logger\n\n\n# The following is a long and boring list of dependencies\nclass PersonOut(pydantic.BaseModel):\n    """Person out."""\n\n    first_name: str\n    second_name: str\n    age: int\n    person_id: int\n\n\nclass FakeDbConnection:\n    """Fake db connection."""\n\n    def __init__(self, *_: typing.Any, **__: typing.Any):\n        ...\n\n\nclass DatabaseFakeService:\n    """Fake database layer."""\n\n    def __init__(self, connection: FakeDbConnection) -> None:\n        # wannabe connection only for test purposes\n        self._connection: FakeDbConnection = connection\n\n    async def __aenter__(self) -> "DatabaseFakeService":\n        """On startup."""\n        return self\n\n    async def __aexit__(self, *_args: typing.Any) -> None:\n        """Wannabe shutdown."""\n        await asyncio.sleep(0)\n\n    async def fetch_person(\n        self, person_id: int\n    ) -> dict[typing.Literal[\'first_name\', \'second_name\', \'age\', \'id\'], str | int]:\n        """Fetch (fictitious) person."""\n        return {\n            \'first_name\': random.choice((\'John\', \'Danku\', \'Ichigo\', \'Sakura\', \'Jugem\', \'Ittō\')),\n            \'second_name\': random.choice(( \'Dow\', \'Kurosaki\', \'Amaterasu\', \'Kasō\', \'HiryuGekizokuShintenRaiho\')),\n            \'age\': random.randint(18, 120),\n            \'id\': person_id,\n        }\n\n\nclass Settings(pydantic.BaseSettings):\n    """Service settings."""\n\n    postgres_dsn: pydantic.PostgresDsn = pydantic.Field(\n        default="postgresql://bakery_tester:bakery_tester@0.0.0.0:5432/bakery_tester"\n    )\n    postgres_pool_min_size: int = 5\n    postgres_pool_max_size: int = 20\n    controller_logger_name: str = "[Controller]"\n\n\nclass ServiceController:\n    """Service controller."""\n\n    def __init__(\n        self,\n        *,\n        database: DatabaseFakeService,\n        logger_name: str,\n    ):\n        self._database = database\n        self._logger_name = logger_name\n\n    def __repr__(self) -> str:\n        return self._logger_name\n\n    async def fetch_person(self, person_id: int, /) -> PersonOut | None:\n        """Fetch person by id."""\n        person: typing.Mapping | None = await self._database.fetch_person(person_id)\n        if not person:\n            return None\n        res: PersonOut = PersonOut(\n            first_name=person["first_name"],\n            second_name=person["second_name"],\n            age=person["age"],\n            person_id=person_id,\n        )\n        return res\n\n\ndef get_settings() -> Settings:\n    """Get settings."""\n    return Settings()\n\n\n# Here is your specific IoC container\nclass MainBakeryIOC(bakery.Bakery):\n    """Main bakery."""\n\n    config: Settings = bakery.Cake(get_settings)\n    _connection: FakeDbConnection = bakery.Cake(\n        FakeDbConnection,\n        config.postgres_dsn,\n        min_size=config.postgres_pool_min_size,\n        max_size=config.postgres_pool_max_size,\n    )\n    database: DatabaseFakeService = bakery.Cake(\n        bakery.Cake(\n            DatabaseFakeService,\n            connection=_connection,\n        )\n    )\n    controller: ServiceController = bakery.Cake(\n        ServiceController,\n        database=database,\n        logger_name=config.controller_logger_name,\n    )\n\n\nasync def startup() -> None:\n    logger.info("Init resources...")\n    bakery.logger = logger\n    await MainBakeryIOC.aopen()\n\n\nasync def shutdown() -> None:\n    logger.info("Shutdown resources...")\n    await MainBakeryIOC.aclose()\n\n\nMY_APP: fastapi.FastAPI = fastapi.FastAPI(\n    on_startup=[startup],\n    on_shutdown=[shutdown],\n)\n\n\n# Finally, an example of how you can use your dependencies\n@MY_APP.get(\'/person/random/\')\nasync def create_person(\n    inversed_controller: ServiceController = fastapi.Depends(MainBakeryIOC.controller),\n) -> PersonOut | None:\n    """Fetch random person from the «database»."""\n    person_id: typing.Final[int] = random.randint(10**1, 10**6)\n    return await inversed_controller.fetch_person(person_id)\n```\nTo run this example, you will need to do the following:\n1. Install dependencies:\n    ```\n    pip install uvicorn fastapi loguru fresh-bakery\n    ```\n1. Save the example text to the file test.py\n1. Run uvicorn\n   ```\n   uvicorn test:MY_APP\n   ```\n1. Open this address in the browser: http://127.0.0.1:8000/docs#/default/create_person_person_random__get\n1. And don\'t forget to read the logs in the console\n\nFor a more complete examples, see [bakery examples](https://github.com/Mityuha/fresh-bakery/tree/main/examples).\n\n## Dependencies\n\nNo dependencies ;)\n\n## Changelog\nYou can see the release history here: https://github.com/Mityuha/fresh-bakery/releases/\n\n---\n\n<p align="center"><i>Fresh Bakery is <a href="https://github.com/Mityuha/fresh-bakery/blob/main/LICENSE">MIT licensed</a> code.</p>\n',
    'author': 'Dmitry Makarov',
    'author_email': 'mit.makaroff@gmail.com',
    'maintainer': 'None',
    'maintainer_email': 'None',
    'url': 'None',
    'packages': packages,
    'package_data': package_data,
    'py_modules': modules,
    'entry_points': entry_points,
    'python_requires': '>=3.6.2,<3.11',
}


setup(**setup_kwargs)
