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

packages = \
['starsessions', 'starsessions.backends']

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

install_requires = \
['itsdangerous>=2.0.1,<3.0.0', 'starlette>=0,<1']

extras_require = \
{'redis': ['aioredis>=2.0.0,<3.0.0']}

setup_kwargs = {
    'name': 'starsessions',
    'version': '2.0.0a0',
    'description': 'Pluggable session support for Starlette.',
    'long_description': '## Starsessions\n\nAdvanced sessions for Starlette and FastAPI frameworks\n\n![PyPI](https://img.shields.io/pypi/v/starsessions)\n![GitHub Workflow Status](https://img.shields.io/github/workflow/status/alex-oleshkevich/starsessions/Lint%20and%20test)\n![GitHub](https://img.shields.io/github/license/alex-oleshkevich/starsessions)\n![Libraries.io dependency status for latest release](https://img.shields.io/librariesio/release/pypi/starsessions)\n![PyPI - Downloads](https://img.shields.io/pypi/dm/starsessions)\n![GitHub Release Date](https://img.shields.io/github/release-date/alex-oleshkevich/starsessions)\n\n## Installation\n\nInstall `starsessions` using PIP or poetry:\n\n```bash\npip install starsessions\n# or\npoetry add starsessions\n```\n\nUse `redis` extra for [Redis support](#redis).\n\n## Quick start\n\nSee example application in [`examples/`](examples) directory of this repository.\n\n## Usage\n\n1. Add `starsessions.SessionMiddleware` to your application to enable session support,\n2. Configure session backend and pass it to the middleware,\n3. Load session in your view using `load_session` utility.\n\n```python\nfrom starlette.applications import Starlette\nfrom starlette.middleware import Middleware\nfrom starlette.responses import JSONResponse\nfrom starlette.routing import Route\n\nfrom starsessions import CookieBackend, load_session, SessionMiddleware\n\n\nasync def index_view(request):\n    await load_session(request)\n\n    session_data = request.session\n    return JSONResponse(session_data)\n\n\nsession_lifetime = 3600 * 24 * 14  # 14 days\nsession_store = CookieBackend(secret_key=\'TOP SECRET\', max_age=session_lifetime)\n\napp = Starlette(\n    middleware=[\n        Middleware(SessionMiddleware, backend=session_store, max_age=session_lifetime),\n    ],\n    routes=[\n        Route(\'/\', index_view),\n    ]\n)\n```\n\n### Session autoload\n\nFor performance reasons session is not autoloaded by default. Sometimes it is annoying to call `load_session` too often.\nWe ship `SessionAutoloadMiddleware` to reduce amount of boilerplate code by autoloading session.\n\nYou have to options: always autoload or autoload for specific paths only. Here are examples:\n\n```python\n\nfrom starlette.middleware import Middleware\n\nfrom starsessions import CookieBackend, SessionAutoloadMiddleware, SessionMiddleware\n\nsession_lifetime = 3600 * 24 * 14  # 14 days\nsession_store = CookieBackend(secret_key=\'TOP SECRET\', max_age=session_lifetime)\n\n# Autoload session for every request\n\nmiddleware = [\n    Middleware(SessionMiddleware, backend=session_store),\n    Middleware(SessionAutoloadMiddleware),\n]\n\n# Autoload session for selected paths\n\nmiddleware = [\n    Middleware(SessionMiddleware, backend=session_store),\n    Middleware(SessionAutoloadMiddleware, paths=[\'/admin\', \'/app\']),\n]\n\n# regex patterns also supported\nimport re\n\nadmin_rx = re.compile(\'/admin*\')\n\nmiddleware = [\n    Middleware(SessionMiddleware, backend=session_store),\n    Middleware(SessionAutoloadMiddleware, paths=[admin_rx]),\n]\n```\n\n### Cookie path\n\nYou can pass `path` arguments to enable session cookies on specific URLs. For example, to activate session cookie only\nfor admin area (which is hosted under `/admin` path prefix), use `path="/admin"` middleware argument.\n\n```python\nfrom starlette.middleware import Middleware\nfrom starsessions import SessionMiddleware\n\nmiddleware = [\n    Middleware(SessionMiddleware, path=\'/admin\'),\n]\n```\n\nAll other URLs not matching value of `path` will not receive cookie thus session will be unavailable.\n\n### Cookie domain\n\nYou can also specify which hosts can receive a cookie by passing `domain` argument to the middleware.\n\n```python\nfrom starlette.middleware import Middleware\nfrom starsessions import SessionMiddleware\n\nmiddleware = [\n    Middleware(SessionMiddleware, domain=\'example.com\'),\n]\n```\n\n> Note, this makes session cookie available for subdomains too.\n> For example, when you set `domain=example.com` then session cookie will be available on subdomains\n> like `app.example.com`.\n\n### Session-only cookies\n\nIf you want session cookie to automatically remove from tbe browser when tab closes then set `max_age` to `0`.\n> Note, this depends on browser implementation!\n\n```python\nfrom starlette.middleware import Middleware\nfrom starsessions import SessionMiddleware\n\nmiddleware = [\n    Middleware(SessionMiddleware, max_age=0),\n]\n```\n\n## Built-in backends\n\n### Memory\n\nClass: `starsessions.InMemoryBackend`\n\nSimply stores data in memory. The data is cleared after server restart. Mostly for use with unit tests.\n\n### CookieBackend\n\nClass: `starsessions.CookieBackend`\n\nStores session data in a signed cookie on the client. This is the default backend.\n\n### Redis\n\nClass: `starsessions.backends.redis.RedisBackend`\n\n> Requires [aioredis](https://aioredis.readthedocs.io/en/latest/getting-started/),\n> use `pip install starsessions[redis]` or `poetry add starsessions[redis]`\n\nStores session data in a Redis server. The backend accepts either connection URL or an instance of `aioredis.Redis`.\n\n```python\nimport aioredis\n\nfrom starsessions.backends.redis import RedisBackend\n\nbackend = RedisBackend(\'redis://localhost\')\n# or\nredis = aioredis.from_url(\'redis://localhost\')\n\nbackend = RedisBackend(connection=redis)\n```\n\nYou can optionally include an expiry time for the Redis keys. This will ensure that sessions get deleted from Redis\nautomatically.\n\n```python\n\nfrom starlette.middleware import Middleware\nfrom starlette.middleware.sessions import SessionMiddleware\n\nfrom starsessions.backends.redis import RedisBackend\n\n...\n\nmax_age = 60 * 60 * 24  # in seconds\n\nbackend = RedisBackend("redis://localhost", expire=max_age)\nmiddleware = [\n    Middleware(SessionMiddleware, backend=backend, max_age=max_age),\n]\n```\n\nNormally, the same `max_age` should be used for Redis expiry times and for the SessionMiddleware.\nMake sure you know what you\'re doing if you need different expiry times.\n\nIt\'s important to note that on every session write, the Redis expiry resets.\nFor example, if you set the Redis expire time for 10 seconds, and you perform another write to the session\nin those 10 seconds, the expire will be extended by 10 seconds.\n\nAbsolute expiry times are still not supported, but very easy to support, so will probably be done in the future.\nFeel free to submit a PR yourself!\n\n## Custom backend\n\nCreating new backends is quite simple. All you need is to extend `starsessions.SessionBackend`\nclass and implement abstract methods.\n\nHere is an example of how we can create a memory-based session backend. Note, it is important that `write` method\nreturns session ID as a string value.\n\n```python\nfrom typing import Dict\n\nfrom starsessions import SessionBackend\n\n\n# instance of class which manages session persistence\n\nclass InMemoryBackend(SessionBackend):\n    def __init__(self):\n        self._storage = {}\n\n    async def read(self, session_id: str) -> Dict:\n        """ Read session data from a data source using session_id. """\n        return self._storage.get(session_id, {})\n\n    async def write(self, session_id: str, data: Dict) -> str:\n        """ Write session data into data source and return session id. """\n        self._storage[session_id] = data\n        return session_id\n\n    async def remove(self, session_id: str):\n        """ Remove session data. """\n        del self._storage[session_id]\n\n    async def exists(self, session_id: str) -> bool:\n        return session_id in self._storage\n```\n\n## Serializers\n\nSometimes you cannot pass raw session data to the backend. The data must be serialized into something the backend can\nhandle.\n\nSome backends (like `RedisBackend`) optionally accept `serializer` argument that will be used to serialize and\ndeserialize session data. By default, we provide (and use) `starsessions.JsonSerializer` but you can implement your own\nby extending `starsessions.Serializer` class.\n\n## Session termination\n\nThe middleware will remove session data and cookie if session has no data. Use `request.session.clear` to empty data.\n\n## Regenerating session ID\n\nSometimes you need a new session ID to avoid session fixation attacks (for example, after successful signs in).\nFor that, use `starsessions.session.regenerate_session_id(connection)` utility.\n\n```python\nfrom starsessions.session import regenerate_session_id\nfrom starlette.responses import Response\n\n\ndef login(request):\n    regenerate_session_id(request)\n    return Response(\'successfully signed in\')\n```\n',
    'author': 'alex.oleshkevich',
    'author_email': 'alex.oleshkevich@gmail.com',
    'maintainer': None,
    'maintainer_email': None,
    'url': 'https://github.com/alex-oleshkevich/starsessions',
    'packages': packages,
    'package_data': package_data,
    'install_requires': install_requires,
    'extras_require': extras_require,
    'python_requires': '>=3.7.0,<4.0.0',
}


setup(**setup_kwargs)
