├── .flake8 ├── .gitignore ├── .pre-commit-config.yaml ├── LICENSE ├── README.md ├── common-data └── movies.json ├── django-subscriptions-rxdb ├── Makefile ├── README.md ├── manage.py ├── pyproject.toml └── src │ ├── api │ ├── __init__.py │ ├── apps.py │ ├── asgi.py │ ├── context.py │ ├── migrations │ │ ├── 0001_initial.py │ │ ├── 0002_auto_20210303_0254.py │ │ └── __init__.py │ ├── models.py │ ├── schema.py │ ├── urls.py │ └── views.py │ └── demo │ ├── __init__.py │ ├── asgi.py │ ├── settings.py │ └── urls.py ├── django-subscriptions ├── Makefile ├── api │ ├── __init__.py │ ├── asgi.py │ ├── context.py │ ├── schema.py │ ├── urls.py │ └── views.py ├── demo │ ├── __init__.py │ ├── asgi.py │ ├── settings.py │ ├── urls.py │ └── wsgi.py ├── manage.py ├── poetry.lock └── pyproject.toml ├── fastapi-sqlalchemy ├── .flake8 ├── .projectroot ├── README.md ├── alembic.ini ├── alembic │ ├── README │ ├── env.py │ ├── script.py.mako │ └── versions │ │ ├── 9bc8667ab6a6_add_initial_models.py │ │ └── bea5e58f3328_add_data.py ├── api │ ├── __init__.py │ ├── definitions │ │ ├── __init__.py │ │ ├── director.py │ │ └── movie.py │ └── schema.py ├── main │ ├── __init__.py │ ├── database.py │ └── models.py ├── poetry.lock ├── pyproject.toml └── setup.cfg └── fastapi ├── .projectroot ├── README.md ├── api ├── __init__.py ├── definitions │ ├── __init__.py │ └── movie.py └── schema.py ├── main └── __init__.py ├── poetry.lock ├── pyproject.toml ├── setup.cfg └── templates └── index.html /.flake8: -------------------------------------------------------------------------------- 1 | [flake8] 2 | max-line-length = 88 3 | exclude=.venv,.git 4 | ignore = W503,E800 5 | extend-ignore = 6 | # See https://github.com/PyCQA/pycodestyle/issues/373 7 | E203, 8 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # Byte-compiled / optimized / DLL files 2 | __pycache__/ 3 | *.py[cod] 4 | *$py.class 5 | 6 | # C extensions 7 | *.so 8 | 9 | # Distribution / packaging 10 | .Python 11 | build/ 12 | develop-eggs/ 13 | dist/ 14 | downloads/ 15 | eggs/ 16 | .eggs/ 17 | lib/ 18 | lib64/ 19 | parts/ 20 | sdist/ 21 | var/ 22 | wheels/ 23 | pip-wheel-metadata/ 24 | share/python-wheels/ 25 | *.egg-info/ 26 | .installed.cfg 27 | *.egg 28 | MANIFEST 29 | 30 | # PyInstaller 31 | # Usually these files are written by a python script from a template 32 | # before PyInstaller builds the exe, so as to inject date/other infos into it. 33 | *.manifest 34 | *.spec 35 | 36 | # Installer logs 37 | pip-log.txt 38 | pip-delete-this-directory.txt 39 | 40 | # Unit test / coverage reports 41 | htmlcov/ 42 | .tox/ 43 | .nox/ 44 | .coverage 45 | .coverage.* 46 | .cache 47 | nosetests.xml 48 | coverage.xml 49 | *.cover 50 | *.py,cover 51 | .hypothesis/ 52 | .pytest_cache/ 53 | 54 | # Translations 55 | *.mo 56 | *.pot 57 | 58 | # Django stuff: 59 | *.log 60 | local_settings.py 61 | db.sqlite3 62 | db.sqlite3-journal 63 | 64 | # Flask stuff: 65 | instance/ 66 | .webassets-cache 67 | 68 | # Scrapy stuff: 69 | .scrapy 70 | 71 | # Sphinx documentation 72 | docs/_build/ 73 | 74 | # PyBuilder 75 | target/ 76 | 77 | # Jupyter Notebook 78 | .ipynb_checkpoints 79 | 80 | # IPython 81 | profile_default/ 82 | ipython_config.py 83 | 84 | # pyenv 85 | .python-version 86 | 87 | # pipenv 88 | # According to pypa/pipenv#598, it is recommended to include Pipfile.lock in version control. 89 | # However, in case of collaboration, if having platform-specific dependencies or dependencies 90 | # having no cross-platform support, pipenv may install dependencies that don't work, or not 91 | # install all needed dependencies. 92 | #Pipfile.lock 93 | 94 | # PEP 582; used by e.g. github.com/David-OConnor/pyflow 95 | __pypackages__/ 96 | 97 | # Celery stuff 98 | celerybeat-schedule 99 | celerybeat.pid 100 | 101 | # SageMath parsed files 102 | *.sage.py 103 | 104 | # Environments 105 | .env 106 | .venv 107 | env/ 108 | venv/ 109 | ENV/ 110 | env.bak/ 111 | venv.bak/ 112 | 113 | # Spyder project settings 114 | .spyderproject 115 | .spyproject 116 | 117 | # Rope project settings 118 | .ropeproject 119 | 120 | # mkdocs documentation 121 | /site 122 | 123 | # mypy 124 | .mypy_cache/ 125 | .dmypy.json 126 | dmypy.json 127 | 128 | # Pyre type checker 129 | .pyre/ 130 | -------------------------------------------------------------------------------- /.pre-commit-config.yaml: -------------------------------------------------------------------------------- 1 | repos: 2 | - repo: https://github.com/PyCQA/flake8 3 | rev: 7.1.1 4 | hooks: 5 | - id: flake8 6 | additional_dependencies: ["flake8-eradicate"] 7 | 8 | - repo: https://github.com/patrick91/pre-commit-alex 9 | rev: aa5da9e54b92ab7284feddeaf52edf14b1690de3 10 | hooks: 11 | - id: alex 12 | exclude: CHANGELOG.md 13 | 14 | - repo: https://github.com/pre-commit/mirrors-prettier 15 | rev: v4.0.0-alpha.8 16 | hooks: 17 | - id: prettier 18 | files: '.*\.mdx?$' 19 | 20 | - repo: https://github.com/pre-commit/pre-commit-hooks 21 | rev: v4.6.0 22 | hooks: 23 | - id: trailing-whitespace 24 | - id: check-merge-conflict 25 | - id: end-of-file-fixer 26 | - id: check-toml 27 | 28 | - repo: https://github.com/humitos/mirrors-autoflake.git 29 | rev: v1.1 30 | hooks: 31 | - id: autoflake 32 | args: ['--in-place', '--remove-all-unused-imports', '--remove-unused-variable'] 33 | 34 | - repo: https://github.com/psf/black 35 | rev: 24.8.0 36 | hooks: 37 | - id: black 38 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2021 Strawberry GraphQL 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Examples 2 | 3 | Examples on how to use Strawberry: 4 | 5 | 1. [Django Subscriptions](/django-subscriptions) 6 | 2. [Django Subscriptions with RXDB](/django-subscriptions-rxdb/) 7 | 3. [FastAPI](/fastapi/) 8 | 4. [FastAPI with SQL-Alchemy](/fastapi-sqlalchemy) 9 | -------------------------------------------------------------------------------- /django-subscriptions-rxdb/Makefile: -------------------------------------------------------------------------------- 1 | install: 2 | poetry install && PYTHONPATH=src poetry run ./manage.py migrate 3 | 4 | install-postgres: 5 | poetry install -E postgres && PYTHONPATH=src poetry run ./manage.py migrate 6 | 7 | run: 8 | PYTHONPATH=src poetry run uvicorn demo.asgi:application --reload --debug --reload-dir src 9 | -------------------------------------------------------------------------------- /django-subscriptions-rxdb/README.md: -------------------------------------------------------------------------------- 1 | # django-subscriptions-rxdb 2 | 3 | ## tl;dr 4 | 5 | This example reproduces the server-side component of the RxDB GraphQL example, with a couple of extras, which can be found [here](https://github.com/pubkey/rxdb/tree/master/examples/graphql). Checkout RxDB and run the GraphQL example. When running Ok, change `export const GRAPHQL_PORT = 10102;` and `export const GRAPHQL_SUBSCRIPTION_PORT = 10103;` ([lines 1 and 3 of this file](https://github.com/pubkey/rxdb/blob/master/examples/graphql/shared.js)) to equal `8000`. Then in the directory of this README file, `make install && make run`. More information about RxDB and GraphQL synchronisation can be found [here](https://rxdb.info/replication-graphql.html). 6 | 7 | ## Requirements 8 | 9 | - [Clone of RxDB](https://github.com/pubkey/rxdb) 10 | - [Python 3.8+](https://www.python.org/downloads/) (might work with other versions, not tested) 11 | - [Poetry](https://python-poetry.org/) 12 | - `make` 13 | - [PostgreSQL](https://www.postgresql.org/) (optional) 14 | 15 | Tested on Ubuntu 20.04, should work everywhere these are available with no changes. 16 | 17 | ## Reason for this example 18 | 19 | While connectivity is getting better around the world every year, every user will always have moments when their connection is spotty (eg. on a plane). With an offline-first, local database and other offline-first tech (service workers, etc.), it is possible to develop web-technology-based applications that will continue to offer much of their functionality offline, with realtime sync when they are online. This really is the best of both worlds, and can give much more fluid and friendly usage when connections are spotty. 20 | 21 | So you already have a Django-based app, and want to add some rich, client-side, offline-first functionality without starting from scratch? This is an example of some of the server-side code for one way of starting out. 22 | 23 | The RxDB component of this is not included here to keep things as light as possible. Offline-first has complexities that need to be mastered, so this is not intended to be a template or even a particularly good way of doing things. It's one rough example to get you started with `rxdb`, `strawberry`, `django` and `broadcaster`. 24 | 25 | ### The full example stack 26 | 27 | The example shows how you can do offline-realtime synchronisation of a local, RxDB database with Django. It uses Strawberry GraphQL subscriptions over websockets for the realtime sync capabilities. The default Django database configured in the `settings` file is Sqlite3 but there is also commented-out config for PostgreSQL. 28 | 29 | If you use PostgreSQL then you will have to set up a database like you would for any PostgreSQL-powered Django site but if you do, the example will also then use PostgreSQL for the realtime notification functionality. To run the example with `postgres`, comment out the `sqlite3` config and put your `postgres` config in the settings file (src/demo/settings.py). You will also need to install extra deps with: 30 | 31 | ``` 32 | make install-postgres 33 | ``` 34 | 35 | Now run `make run` as usual to run it. 36 | 37 | This extended setup shows how you can have multiple instances of your Django (in a Kubernetes cluster, for example), and realtime notifications will work for any client connected to any of the servers. This example uses [broadcaster](https://github.com/encode/broadcaster) for subscription notifications which, in addition to `postgres`, supports `memory` (for a single node), `redis` and `kafka`. If your `django` is not using `postgres` and/or you are using one of the other options for caching or messaging, you might want to use one of those. It should work if you follow the `broadcaster` docs for the connection string. 38 | -------------------------------------------------------------------------------- /django-subscriptions-rxdb/manage.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | """Django's command-line utility for administrative tasks.""" 3 | import os 4 | import sys 5 | 6 | 7 | def main(): 8 | """Run administrative tasks.""" 9 | os.environ.setdefault("DJANGO_SETTINGS_MODULE", "demo.settings") 10 | try: 11 | from django.core.management import execute_from_command_line 12 | except ImportError as exc: 13 | raise ImportError( 14 | "Couldn't import Django. Are you sure it's installed and " 15 | "available on your PYTHONPATH environment variable? Did you " 16 | "forget to activate a virtual environment?" 17 | ) from exc 18 | execute_from_command_line(sys.argv) 19 | 20 | 21 | if __name__ == "__main__": 22 | main() 23 | -------------------------------------------------------------------------------- /django-subscriptions-rxdb/pyproject.toml: -------------------------------------------------------------------------------- 1 | [tool.poetry] 2 | name = "django-subscriptions-rxdb" 3 | version = "0.1.0" 4 | description = "" 5 | authors = ["Patrick Arminio ", "Anton Melser "] 6 | license = "MIT" 7 | 8 | [tool.poetry.dependencies] 9 | python = "^3.8" 10 | strawberry-graphql = "^0.46.0" 11 | Django = "^3.1.7" 12 | uvicorn = {extras = ["standard"], version = "^0.13.4"} 13 | django-cors-headers = "^3.7.0" 14 | psycopg2-binary = {version = "^2.8.6", extras = ["postgres"], optional = true} 15 | broadcaster = {extras = ["postgres"], version = "^0.2.0"} 16 | strawberry-graphql-django = "^0.0.6" 17 | 18 | [tool.poetry.extras] 19 | postgres = ["psycopg2-binary"] 20 | 21 | 22 | [tool.poetry.dev-dependencies] 23 | black = {version = "^20.8b1", allow-prereleases = true} 24 | flake8 = "^3.8.4" 25 | isort = "^5.7.0" 26 | 27 | [build-system] 28 | requires = ["poetry-core>=1.0.0"] 29 | build-backend = "poetry.core.masonry.api" 30 | -------------------------------------------------------------------------------- /django-subscriptions-rxdb/src/api/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/strawberry-graphql/examples/8a1cddbc41d3e7dfdcf2a6e1192b2bb730e3b7a1/django-subscriptions-rxdb/src/api/__init__.py -------------------------------------------------------------------------------- /django-subscriptions-rxdb/src/api/apps.py: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 -*- 2 | 3 | from django.apps import AppConfig 4 | 5 | 6 | class ApiConfig(AppConfig): 7 | name = "api" 8 | -------------------------------------------------------------------------------- /django-subscriptions-rxdb/src/api/asgi.py: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 -*- 2 | 3 | import typing 4 | 5 | from starlette.requests import Request 6 | from starlette.websockets import WebSocket 7 | from strawberry.asgi import GraphQL 8 | 9 | from .context import Context, get_broadcast 10 | 11 | 12 | class MyGraphQL(GraphQL): 13 | async def get_context( 14 | self, request: typing.Union[Request, WebSocket] 15 | ) -> typing.Optional[typing.Any]: 16 | broadcast = await get_broadcast() 17 | 18 | return Context(broadcast) 19 | -------------------------------------------------------------------------------- /django-subscriptions-rxdb/src/api/context.py: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 -*- 2 | 3 | from dataclasses import dataclass 4 | 5 | from broadcaster import Broadcast 6 | from django.db import connection 7 | 8 | broadcast = None 9 | 10 | 11 | async def get_broadcast(): 12 | global broadcast 13 | 14 | if not broadcast: 15 | dbinfo = connection.settings_dict 16 | if dbinfo.get("ENGINE") == "django.db.backends.postgresql": 17 | host = ( 18 | f"{dbinfo.get('HOST')}:{dbinfo.get('PORT')}" 19 | if dbinfo.get("PORT") 20 | else dbinfo.get("HOST") 21 | ) 22 | dsnstr = ( 23 | f"postgresql://{dbinfo.get('USER')}:" 24 | f"{dbinfo.get('PASSWORD')}@{host}/{dbinfo.get('NAME')}" 25 | ) 26 | broadcast = Broadcast(dsnstr) 27 | else: 28 | broadcast = Broadcast("memory://") 29 | 30 | await broadcast.connect() 31 | 32 | return broadcast 33 | 34 | 35 | @dataclass 36 | class Context: 37 | broadcast: Broadcast 38 | -------------------------------------------------------------------------------- /django-subscriptions-rxdb/src/api/migrations/0001_initial.py: -------------------------------------------------------------------------------- 1 | # Generated by Django 3.1.7 on 2021-02-28 03:58 2 | 3 | from django.db import migrations, models 4 | 5 | 6 | class Migration(migrations.Migration): 7 | 8 | initial = True 9 | 10 | dependencies = [] 11 | 12 | operations = [ 13 | migrations.CreateModel( 14 | name="Hero", 15 | fields=[ 16 | ( 17 | "id", 18 | models.CharField(max_length=100, primary_key=True, serialize=False), 19 | ), 20 | ("color", models.CharField(max_length=100)), 21 | ("name", models.CharField(max_length=100, null=True)), 22 | ("updatedAt", models.FloatField(max_length=100, null=True)), 23 | ("deleted", models.BooleanField(default=True)), 24 | ], 25 | ), 26 | ] 27 | -------------------------------------------------------------------------------- /django-subscriptions-rxdb/src/api/migrations/0002_auto_20210303_0254.py: -------------------------------------------------------------------------------- 1 | # Generated by Django 3.1.7 on 2021-03-03 02:54 2 | 3 | from django.db import migrations, models 4 | 5 | 6 | class Migration(migrations.Migration): 7 | 8 | dependencies = [ 9 | ("api", "0001_initial"), 10 | ] 11 | 12 | operations = [ 13 | migrations.AlterField( 14 | model_name="hero", 15 | name="deleted", 16 | field=models.BooleanField(), 17 | ), 18 | ] 19 | -------------------------------------------------------------------------------- /django-subscriptions-rxdb/src/api/migrations/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/strawberry-graphql/examples/8a1cddbc41d3e7dfdcf2a6e1192b2bb730e3b7a1/django-subscriptions-rxdb/src/api/migrations/__init__.py -------------------------------------------------------------------------------- /django-subscriptions-rxdb/src/api/models.py: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 -*- 2 | 3 | from django.db import models 4 | 5 | 6 | class Hero(models.Model): 7 | id = models.CharField(max_length=100, primary_key=True) 8 | color = models.CharField(max_length=100) 9 | name = models.CharField(max_length=100, null=True) 10 | updatedAt = models.FloatField(max_length=100, null=True) 11 | deleted = models.BooleanField() 12 | -------------------------------------------------------------------------------- /django-subscriptions-rxdb/src/api/schema.py: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 -*- 2 | 3 | import time 4 | from typing import List, Optional 5 | 6 | import strawberry 7 | from asgiref.sync import sync_to_async 8 | from django.core.serializers import deserialize, serialize 9 | from django.db.models import Q 10 | from strawberry_django import ModelResolver 11 | 12 | from api import models 13 | 14 | 15 | class HeroResolver(ModelResolver): 16 | model = models.Hero 17 | 18 | 19 | # type Hero { 20 | # id: String 21 | # name: String 22 | # color: String! 23 | # updatedAt: Float 24 | # deleted: Boolean! 25 | # } 26 | class Hero(HeroResolver.output_type): 27 | pass 28 | 29 | 30 | # input HeroInput { 31 | # id: String 32 | # name: String 33 | # color: String! 34 | # updatedAt: Float 35 | # deleted: Boolean! 36 | # } 37 | # The client code expects the input type to be called "HeroInput", 38 | # not "CreateHero", which is the default We therefore need to create a new type 39 | # via the strawberry.input decorator 40 | @strawberry.input 41 | class HeroInput(HeroResolver.create_input_type): 42 | pass 43 | 44 | 45 | def filterHeroes( 46 | limit: int, id: Optional[str] = "", updatedAt: Optional[float] = -1 47 | ) -> List[Hero]: 48 | qs = [] 49 | if not updatedAt: 50 | qs = [] 51 | else: 52 | qs = [(Q(updatedAt__gt=updatedAt) | (Q(updatedAt=updatedAt) & Q(id__gt=id)))] 53 | 54 | return [ 55 | Hero( 56 | id=h.id, 57 | name=h.name, 58 | color=h.color, 59 | updatedAt=h.updatedAt, 60 | deleted=h.deleted, 61 | ) 62 | for h in models.Hero.objects.order_by("updatedAt", "id").filter(Q(*qs))[:limit] 63 | ] 64 | 65 | 66 | @strawberry.type 67 | class Query: 68 | # to include the auto-generated methods from strawberry-graphql-django: 69 | # - hero(id: ID!): Hero! 70 | # - heros(filters: [String!] = null): [Hero!]! 71 | # declare the class as 72 | # class Query(HeroResolver.query()): 73 | 74 | # type Query { 75 | # feedHero(id: String, updatedAt: Float, limit: Int!): [Hero!]! 76 | # } 77 | @strawberry.field 78 | async def feed_hero( 79 | limit: int, id: Optional[str] = "", updatedAt: Optional[float] = -1 80 | ) -> List[Hero]: 81 | return await sync_to_async(filterHeroes)(limit, id, updatedAt) 82 | 83 | 84 | @strawberry.type 85 | class Mutation: 86 | # type Mutation { 87 | # setHero(hero: HeroInput): Hero 88 | # } 89 | @strawberry.mutation 90 | async def set_hero(self, info, hero: HeroInput = None) -> Hero: 91 | try: 92 | dhero = await sync_to_async(models.Hero.objects.get)(id=hero.id) 93 | except models.Hero.DoesNotExist: 94 | dhero = models.Hero(id=hero.id) 95 | 96 | dhero.color = hero.color 97 | dhero.name = hero.name 98 | dhero.updatedAt = int(time.time()) 99 | dhero.deleted = hero.deleted 100 | 101 | await sync_to_async(dhero.save)() 102 | await info.context.broadcast.publish( 103 | channel="heros", message=serialize("json", [dhero]) 104 | ) 105 | 106 | return Hero( 107 | id=dhero.id, 108 | color=dhero.color, 109 | name=dhero.name, 110 | updatedAt=dhero.updatedAt, 111 | deleted=dhero.deleted, 112 | ) 113 | 114 | 115 | @strawberry.type 116 | class Subscription: 117 | # type Subscription { 118 | # changedHero(token: String!): Hero 119 | # } 120 | @strawberry.subscription 121 | async def changed_hero(self, info, token: str) -> Hero: 122 | async with info.context.broadcast.subscribe(channel="heros") as subscriber: 123 | async for event in subscriber: 124 | hero = list(deserialize("json", event.message))[0].object 125 | yield Hero( 126 | id=hero.id, 127 | color=hero.color, 128 | name=hero.name, 129 | updatedAt=hero.updatedAt, 130 | deleted=hero.deleted, 131 | ) 132 | 133 | 134 | # schema { 135 | # query: Query 136 | # mutation: Mutation 137 | # subscription: Subscription 138 | # } 139 | schema = strawberry.Schema(query=Query, mutation=Mutation, subscription=Subscription) 140 | -------------------------------------------------------------------------------- /django-subscriptions-rxdb/src/api/urls.py: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 -*- 2 | 3 | from django.urls import path 4 | 5 | from .schema import schema 6 | from .views import AsyncGraphQLView 7 | 8 | urlpatterns = [path("graphql", AsyncGraphQLView.as_view(schema=schema))] 9 | -------------------------------------------------------------------------------- /django-subscriptions-rxdb/src/api/views.py: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 -*- 2 | 3 | import os 4 | 5 | import strawberry 6 | from django.http import Http404, HttpRequest 7 | from django.template import RequestContext, Template 8 | from django.template.exceptions import TemplateDoesNotExist 9 | from django.template.loader import render_to_string 10 | from django.template.response import TemplateResponse 11 | from strawberry.django.views import AsyncGraphQLView as StrawberryAsyncGraphQLView 12 | 13 | from .context import Context, get_broadcast 14 | 15 | 16 | class AsyncGraphQLView(StrawberryAsyncGraphQLView): 17 | async def get_context(self, request: HttpRequest) -> Context: 18 | broadcast = await get_broadcast() 19 | 20 | return Context(broadcast) 21 | 22 | def _render_graphiql(self, request: HttpRequest, context=None): 23 | if not self.graphiql: 24 | raise Http404() 25 | 26 | try: 27 | template = Template(render_to_string("graphql/graphiql.html")) 28 | except TemplateDoesNotExist: 29 | template = Template( 30 | open( 31 | os.path.join( 32 | os.path.dirname(os.path.abspath(strawberry.__file__)), 33 | "static/graphiql.html", 34 | ), 35 | "r", 36 | ).read() 37 | ) 38 | 39 | context = context or {} 40 | # THIS enables subscriptions 41 | context.update({"SUBSCRIPTION_ENABLED": "true"}) 42 | 43 | response = TemplateResponse(request=request, template=None, context=context) 44 | response.content = template.render(RequestContext(request, context)) 45 | 46 | return response 47 | -------------------------------------------------------------------------------- /django-subscriptions-rxdb/src/demo/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/strawberry-graphql/examples/8a1cddbc41d3e7dfdcf2a6e1192b2bb730e3b7a1/django-subscriptions-rxdb/src/demo/__init__.py -------------------------------------------------------------------------------- /django-subscriptions-rxdb/src/demo/asgi.py: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 -*- 2 | 3 | import os 4 | 5 | from django.core.asgi import get_asgi_application 6 | from starlette.websockets import WebSocketDisconnect 7 | 8 | from api.asgi import MyGraphQL 9 | 10 | os.environ.setdefault("DJANGO_SETTINGS_MODULE", "demo.settings") 11 | 12 | django_application = get_asgi_application() 13 | 14 | 15 | async def application(scope, receive, send): 16 | if scope["type"] == "http": 17 | await django_application(scope, receive, send) 18 | elif scope["type"] == "websocket": 19 | try: 20 | import api.schema 21 | 22 | graphql_app = MyGraphQL( 23 | api.schema.schema, keep_alive=True, keep_alive_interval=5 24 | ) 25 | 26 | await graphql_app(scope, receive, send) 27 | except WebSocketDisconnect: 28 | pass 29 | else: 30 | raise NotImplementedError(f"Unknown scope type {scope['type']}") 31 | -------------------------------------------------------------------------------- /django-subscriptions-rxdb/src/demo/settings.py: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 -*- 2 | 3 | from pathlib import Path 4 | 5 | BASE_DIR = Path(__file__).resolve().parent.parent.parent 6 | SECRET_KEY = "p-h@br&tcqetcsaa%))9%5-80qjv&*-2_@6eddvp!3m)z#kyq%" 7 | DEBUG = True 8 | 9 | ALLOWED_HOSTS = [] 10 | INSTALLED_APPS = [ 11 | "django.contrib.admin", 12 | "django.contrib.auth", 13 | "django.contrib.contenttypes", 14 | "django.contrib.sessions", 15 | "django.contrib.messages", 16 | "django.contrib.staticfiles", 17 | "corsheaders", 18 | "api", 19 | ] 20 | 21 | MIDDLEWARE = [ 22 | "django.middleware.security.SecurityMiddleware", 23 | "django.contrib.sessions.middleware.SessionMiddleware", 24 | "corsheaders.middleware.CorsMiddleware", 25 | "django.middleware.common.CommonMiddleware", 26 | "django.middleware.csrf.CsrfViewMiddleware", 27 | "django.contrib.auth.middleware.AuthenticationMiddleware", 28 | "django.contrib.messages.middleware.MessageMiddleware", 29 | "django.middleware.clickjacking.XFrameOptionsMiddleware", 30 | ] 31 | 32 | ROOT_URLCONF = "demo.urls" 33 | 34 | TEMPLATES = [ 35 | { 36 | "BACKEND": "django.template.backends.django.DjangoTemplates", 37 | "DIRS": [], 38 | "APP_DIRS": True, 39 | "OPTIONS": { 40 | "context_processors": [ 41 | "django.template.context_processors.debug", 42 | "django.template.context_processors.request", 43 | "django.contrib.auth.context_processors.auth", 44 | "django.contrib.messages.context_processors.messages", 45 | ], 46 | }, 47 | }, 48 | ] 49 | 50 | ASGI_APPLICATION = "demo.asgi.application" 51 | 52 | DATABASES = { 53 | "default": { 54 | "ENGINE": "django.db.backends.sqlite3", 55 | "NAME": BASE_DIR / "db.sqlite3", 56 | } 57 | # "default": { 58 | # 'ENGINE': 'django.db.backends.postgresql', 59 | # 'NAME': 'djstrawsync', 60 | # 'USER': 'strawberry', 61 | # "PASSWORD": "strawword", 62 | # "HOST": "127.0.0.1", 63 | # "PORT": "5432", 64 | # }, 65 | } 66 | 67 | AUTH_PASSWORD_VALIDATORS = [ 68 | { 69 | "NAME": ( 70 | "django.contrib.auth.password_validation.UserAttributeSimilarityValidator" 71 | ), 72 | }, 73 | { 74 | "NAME": "django.contrib.auth.password_validation.MinimumLengthValidator", 75 | }, 76 | { 77 | "NAME": "django.contrib.auth.password_validation.CommonPasswordValidator", 78 | }, 79 | { 80 | "NAME": "django.contrib.auth.password_validation.NumericPasswordValidator", 81 | }, 82 | ] 83 | 84 | LANGUAGE_CODE = "en-us" 85 | TIME_ZONE = "UTC" 86 | USE_I18N = True 87 | USE_L10N = True 88 | USE_TZ = True 89 | 90 | STATIC_URL = "/static/" 91 | 92 | CORS_ALLOW_ALL_ORIGINS = True 93 | -------------------------------------------------------------------------------- /django-subscriptions-rxdb/src/demo/urls.py: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 -*- 2 | 3 | from django.contrib import admin 4 | from django.urls import include, path 5 | 6 | urlpatterns = [ 7 | path("admin/", admin.site.urls), 8 | path("", include("api.urls")), 9 | ] 10 | -------------------------------------------------------------------------------- /django-subscriptions/Makefile: -------------------------------------------------------------------------------- 1 | run: 2 | poetry run uvicorn demo.asgi:application --reload --debug 3 | -------------------------------------------------------------------------------- /django-subscriptions/api/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/strawberry-graphql/examples/8a1cddbc41d3e7dfdcf2a6e1192b2bb730e3b7a1/django-subscriptions/api/__init__.py -------------------------------------------------------------------------------- /django-subscriptions/api/asgi.py: -------------------------------------------------------------------------------- 1 | import typing 2 | 3 | from starlette.requests import Request 4 | from starlette.websockets import WebSocket 5 | from strawberry.asgi import GraphQL 6 | 7 | from .context import Context, get_broadcast 8 | 9 | 10 | class MyGraphQL(GraphQL): 11 | async def get_context( 12 | self, request: typing.Union[Request, WebSocket] 13 | ) -> typing.Optional[typing.Any]: 14 | broadcast = await get_broadcast() 15 | 16 | return Context(broadcast) 17 | -------------------------------------------------------------------------------- /django-subscriptions/api/context.py: -------------------------------------------------------------------------------- 1 | from dataclasses import dataclass 2 | 3 | from broadcaster import Broadcast 4 | 5 | broadcast = None 6 | 7 | 8 | async def get_broadcast(): 9 | global broadcast 10 | 11 | if not broadcast: 12 | broadcast = Broadcast("memory://") 13 | 14 | await broadcast.connect() 15 | 16 | return broadcast 17 | 18 | 19 | @dataclass 20 | class Context: 21 | broadcast: Broadcast 22 | -------------------------------------------------------------------------------- /django-subscriptions/api/schema.py: -------------------------------------------------------------------------------- 1 | import asyncio 2 | 3 | import strawberry 4 | 5 | 6 | @strawberry.type 7 | class Query: 8 | @strawberry.field 9 | def hello() -> str: 10 | return "world" 11 | 12 | 13 | @strawberry.type 14 | class Mutation: 15 | @strawberry.field 16 | async def send_message(self, info, message: str) -> bool: 17 | print("sending on_message") 18 | print(id(info.context.broadcast)) 19 | await info.context.broadcast.publish(channel="chatroom", message=message) 20 | 21 | return True 22 | 23 | 24 | @strawberry.type 25 | class Subscription: 26 | @strawberry.subscription 27 | async def on_message(self, info) -> str: 28 | print("starting on_message") 29 | print(id(info.context.broadcast)) 30 | 31 | async with info.context.broadcast.subscribe(channel="chatroom") as subscriber: 32 | print(f"{subscriber=}") 33 | async for event in subscriber: 34 | print(f"{event=}") 35 | yield event.message 36 | 37 | @strawberry.subscription 38 | async def count(self, target: int = 100) -> int: 39 | for i in range(target): 40 | yield i 41 | await asyncio.sleep(0.5) 42 | 43 | 44 | schema = strawberry.Schema(query=Query, mutation=Mutation, subscription=Subscription) 45 | -------------------------------------------------------------------------------- /django-subscriptions/api/urls.py: -------------------------------------------------------------------------------- 1 | from django.urls import path 2 | 3 | from .schema import schema 4 | from .views import AsyncGraphQLView 5 | 6 | urlpatterns = [path("graphql", AsyncGraphQLView.as_view(schema=schema))] 7 | -------------------------------------------------------------------------------- /django-subscriptions/api/views.py: -------------------------------------------------------------------------------- 1 | import os 2 | 3 | import strawberry 4 | from django.http import Http404, HttpRequest 5 | from django.template import RequestContext, Template 6 | from django.template.exceptions import TemplateDoesNotExist 7 | from django.template.loader import render_to_string 8 | from django.template.response import TemplateResponse 9 | from strawberry.django.views import AsyncGraphQLView as StrawberryAsyncGraphQLView 10 | 11 | from .context import Context, get_broadcast 12 | 13 | 14 | class AsyncGraphQLView(StrawberryAsyncGraphQLView): 15 | async def get_context(self, request: HttpRequest) -> Context: 16 | broadcast = await get_broadcast() 17 | 18 | return Context(broadcast) 19 | 20 | def _render_graphiql(self, request: HttpRequest, context=None): 21 | if not self.graphiql: 22 | raise Http404() 23 | 24 | try: 25 | template = Template(render_to_string("graphql/graphiql.html")) 26 | except TemplateDoesNotExist: 27 | template = Template( 28 | open( 29 | os.path.join( 30 | os.path.dirname(os.path.abspath(strawberry.__file__)), 31 | "static/graphiql.html", 32 | ), 33 | "r", 34 | ).read() 35 | ) 36 | 37 | context = context or {} 38 | # THIS enables subscriptions 39 | context.update({"SUBSCRIPTION_ENABLED": "true"}) 40 | 41 | response = TemplateResponse(request=request, template=None, context=context) 42 | response.content = template.render(RequestContext(request, context)) 43 | 44 | return response 45 | -------------------------------------------------------------------------------- /django-subscriptions/demo/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/strawberry-graphql/examples/8a1cddbc41d3e7dfdcf2a6e1192b2bb730e3b7a1/django-subscriptions/demo/__init__.py -------------------------------------------------------------------------------- /django-subscriptions/demo/asgi.py: -------------------------------------------------------------------------------- 1 | import os 2 | 3 | from api.asgi import MyGraphQL 4 | from django.core.asgi import get_asgi_application 5 | from starlette.websockets import WebSocketDisconnect 6 | 7 | os.environ.setdefault("DJANGO_SETTINGS_MODULE", "demo.settings") 8 | 9 | django_application = get_asgi_application() 10 | 11 | 12 | async def application(scope, receive, send): 13 | # TODO: always use ASGI graphql 14 | 15 | if scope["type"] == "http": 16 | await django_application(scope, receive, send) 17 | elif scope["type"] == "websocket": 18 | try: 19 | from api.schema import schema 20 | 21 | graphql_app = MyGraphQL(schema, keep_alive=True, keep_alive_interval=5) 22 | 23 | await graphql_app(scope, receive, send) 24 | except WebSocketDisconnect: 25 | pass 26 | else: 27 | raise NotImplementedError(f"Unknown scope type {scope['type']}") 28 | -------------------------------------------------------------------------------- /django-subscriptions/demo/settings.py: -------------------------------------------------------------------------------- 1 | """ 2 | Django settings for demo project. 3 | 4 | Generated by 'django-admin startproject' using Django 3.1.7. 5 | 6 | For more information on this file, see 7 | https://docs.djangoproject.com/en/3.1/topics/settings/ 8 | 9 | For the full list of settings and their values, see 10 | https://docs.djangoproject.com/en/3.1/ref/settings/ 11 | """ 12 | 13 | from pathlib import Path 14 | 15 | # Build paths inside the project like this: BASE_DIR / 'subdir'. 16 | BASE_DIR = Path(__file__).resolve().parent.parent 17 | 18 | 19 | # Quick-start development settings - unsuitable for production 20 | # See https://docs.djangoproject.com/en/3.1/howto/deployment/checklist/ 21 | 22 | # SECURITY WARNING: keep the secret key used in production secret! 23 | SECRET_KEY = "p-h@br&tcqetcsaa%))9%5-80qjv&*-2_@6eddvp!3m)z#kyq%" 24 | 25 | # SECURITY WARNING: don't run with debug turned on in production! 26 | DEBUG = True 27 | 28 | ALLOWED_HOSTS = [] 29 | 30 | 31 | # Application definition 32 | 33 | INSTALLED_APPS = [ 34 | "django.contrib.admin", 35 | "django.contrib.auth", 36 | "django.contrib.contenttypes", 37 | "django.contrib.sessions", 38 | "django.contrib.messages", 39 | "django.contrib.staticfiles", 40 | ] 41 | 42 | MIDDLEWARE = [ 43 | "django.middleware.security.SecurityMiddleware", 44 | "django.contrib.sessions.middleware.SessionMiddleware", 45 | "django.middleware.common.CommonMiddleware", 46 | "django.middleware.csrf.CsrfViewMiddleware", 47 | "django.contrib.auth.middleware.AuthenticationMiddleware", 48 | "django.contrib.messages.middleware.MessageMiddleware", 49 | "django.middleware.clickjacking.XFrameOptionsMiddleware", 50 | ] 51 | 52 | ROOT_URLCONF = "demo.urls" 53 | 54 | TEMPLATES = [ 55 | { 56 | "BACKEND": "django.template.backends.django.DjangoTemplates", 57 | "DIRS": [], 58 | "APP_DIRS": True, 59 | "OPTIONS": { 60 | "context_processors": [ 61 | "django.template.context_processors.debug", 62 | "django.template.context_processors.request", 63 | "django.contrib.auth.context_processors.auth", 64 | "django.contrib.messages.context_processors.messages", 65 | ], 66 | }, 67 | }, 68 | ] 69 | 70 | WSGI_APPLICATION = "demo.wsgi.application" 71 | 72 | 73 | # Database 74 | # https://docs.djangoproject.com/en/3.1/ref/settings/#databases 75 | 76 | DATABASES = { 77 | "default": { 78 | "ENGINE": "django.db.backends.sqlite3", 79 | "NAME": BASE_DIR / "db.sqlite3", 80 | } 81 | } 82 | 83 | 84 | # Password validation 85 | # https://docs.djangoproject.com/en/3.1/ref/settings/#auth-password-validators 86 | 87 | AUTH_PASSWORD_VALIDATORS = [ 88 | { 89 | "NAME": ( 90 | "django.contrib.auth.password_validation.UserAttributeSimilarityValidator" 91 | ), 92 | }, 93 | { 94 | "NAME": "django.contrib.auth.password_validation.MinimumLengthValidator", 95 | }, 96 | { 97 | "NAME": "django.contrib.auth.password_validation.CommonPasswordValidator", 98 | }, 99 | { 100 | "NAME": "django.contrib.auth.password_validation.NumericPasswordValidator", 101 | }, 102 | ] 103 | 104 | 105 | # Internationalization 106 | # https://docs.djangoproject.com/en/3.1/topics/i18n/ 107 | 108 | LANGUAGE_CODE = "en-us" 109 | 110 | TIME_ZONE = "UTC" 111 | 112 | USE_I18N = True 113 | 114 | USE_L10N = True 115 | 116 | USE_TZ = True 117 | 118 | 119 | # Static files (CSS, JavaScript, Images) 120 | # https://docs.djangoproject.com/en/3.1/howto/static-files/ 121 | 122 | STATIC_URL = "/static/" 123 | -------------------------------------------------------------------------------- /django-subscriptions/demo/urls.py: -------------------------------------------------------------------------------- 1 | from django.contrib import admin 2 | from django.urls import include, path 3 | 4 | urlpatterns = [ 5 | path("admin/", admin.site.urls), 6 | path("", include("api.urls")), 7 | ] 8 | -------------------------------------------------------------------------------- /django-subscriptions/demo/wsgi.py: -------------------------------------------------------------------------------- 1 | """ 2 | WSGI config for demo project. 3 | 4 | It exposes the WSGI callable as a module-level variable named ``application``. 5 | 6 | For more information on this file, see 7 | https://docs.djangoproject.com/en/3.1/howto/deployment/wsgi/ 8 | """ 9 | 10 | import os 11 | 12 | from django.core.wsgi import get_wsgi_application 13 | 14 | os.environ.setdefault("DJANGO_SETTINGS_MODULE", "demo.settings") 15 | 16 | application = get_wsgi_application() 17 | -------------------------------------------------------------------------------- /django-subscriptions/manage.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | """Django's command-line utility for administrative tasks.""" 3 | import os 4 | import sys 5 | 6 | 7 | def main(): 8 | """Run administrative tasks.""" 9 | os.environ.setdefault("DJANGO_SETTINGS_MODULE", "demo.settings") 10 | try: 11 | from django.core.management import execute_from_command_line 12 | except ImportError as exc: 13 | raise ImportError( 14 | "Couldn't import Django. Are you sure it's installed and " 15 | "available on your PYTHONPATH environment variable? Did you " 16 | "forget to activate a virtual environment?" 17 | ) from exc 18 | execute_from_command_line(sys.argv) 19 | 20 | 21 | if __name__ == "__main__": 22 | main() 23 | -------------------------------------------------------------------------------- /django-subscriptions/poetry.lock: -------------------------------------------------------------------------------- 1 | [[package]] 2 | name = "appdirs" 3 | version = "1.4.4" 4 | description = "A small Python module for determining appropriate platform-specific dirs, e.g. a \"user data dir\"." 5 | category = "dev" 6 | optional = false 7 | python-versions = "*" 8 | 9 | [[package]] 10 | name = "asgiref" 11 | version = "3.3.1" 12 | description = "ASGI specs, helper code, and adapters" 13 | category = "main" 14 | optional = false 15 | python-versions = ">=3.5" 16 | 17 | [package.extras] 18 | tests = ["pytest", "pytest-asyncio"] 19 | 20 | [[package]] 21 | name = "black" 22 | version = "20.8b1" 23 | description = "The uncompromising code formatter." 24 | category = "dev" 25 | optional = false 26 | python-versions = ">=3.6" 27 | 28 | [package.dependencies] 29 | appdirs = "*" 30 | click = ">=7.1.2" 31 | mypy-extensions = ">=0.4.3" 32 | pathspec = ">=0.6,<1" 33 | regex = ">=2020.1.8" 34 | toml = ">=0.10.1" 35 | typed-ast = ">=1.4.0" 36 | typing-extensions = ">=3.7.4" 37 | 38 | [package.extras] 39 | colorama = ["colorama (>=0.4.3)"] 40 | d = ["aiohttp (>=3.3.2)", "aiohttp-cors"] 41 | 42 | [[package]] 43 | name = "broadcaster" 44 | version = "0.2.0" 45 | description = "Simple broadcast channels." 46 | category = "main" 47 | optional = false 48 | python-versions = ">=3.7" 49 | 50 | [package.extras] 51 | kafka = ["aiokafka"] 52 | postgres = ["asyncpg"] 53 | redis = ["asyncio-redis"] 54 | 55 | [[package]] 56 | name = "cached-property" 57 | version = "1.5.2" 58 | description = "A decorator for caching properties in classes." 59 | category = "main" 60 | optional = false 61 | python-versions = "*" 62 | 63 | [[package]] 64 | name = "click" 65 | version = "7.1.2" 66 | description = "Composable command line interface toolkit" 67 | category = "main" 68 | optional = false 69 | python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*, !=3.4.*" 70 | 71 | [[package]] 72 | name = "colorama" 73 | version = "0.4.4" 74 | description = "Cross-platform colored terminal text." 75 | category = "main" 76 | optional = false 77 | python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*, !=3.4.*" 78 | 79 | [[package]] 80 | name = "django" 81 | version = "3.1.7" 82 | description = "A high-level Python Web framework that encourages rapid development and clean, pragmatic design." 83 | category = "main" 84 | optional = false 85 | python-versions = ">=3.6" 86 | 87 | [package.dependencies] 88 | asgiref = ">=3.2.10,<4" 89 | pytz = "*" 90 | sqlparse = ">=0.2.2" 91 | 92 | [package.extras] 93 | argon2 = ["argon2-cffi (>=16.1.0)"] 94 | bcrypt = ["bcrypt"] 95 | 96 | [[package]] 97 | name = "flake8" 98 | version = "3.8.4" 99 | description = "the modular source code checker: pep8 pyflakes and co" 100 | category = "dev" 101 | optional = false 102 | python-versions = "!=3.0.*,!=3.1.*,!=3.2.*,!=3.3.*,>=2.7" 103 | 104 | [package.dependencies] 105 | mccabe = ">=0.6.0,<0.7.0" 106 | pycodestyle = ">=2.6.0a1,<2.7.0" 107 | pyflakes = ">=2.2.0,<2.3.0" 108 | 109 | [[package]] 110 | name = "graphql-core" 111 | version = "3.1.3" 112 | description = "GraphQL implementation for Python, a port of GraphQL.js, the JavaScript reference implementation for GraphQL." 113 | category = "main" 114 | optional = false 115 | python-versions = ">=3.6,<4" 116 | 117 | [[package]] 118 | name = "h11" 119 | version = "0.12.0" 120 | description = "A pure-Python, bring-your-own-I/O implementation of HTTP/1.1" 121 | category = "main" 122 | optional = false 123 | python-versions = ">=3.6" 124 | 125 | [[package]] 126 | name = "httptools" 127 | version = "0.1.1" 128 | description = "A collection of framework independent HTTP protocol utils." 129 | category = "main" 130 | optional = false 131 | python-versions = "*" 132 | 133 | [package.extras] 134 | test = ["Cython (==0.29.14)"] 135 | 136 | [[package]] 137 | name = "hupper" 138 | version = "1.10.2" 139 | description = "Integrated process monitor for developing and reloading daemons." 140 | category = "main" 141 | optional = false 142 | python-versions = ">=2.7,!=3.0.*,!=3.1.*,!=3.2.*,!=3.3.*" 143 | 144 | [package.extras] 145 | docs = ["watchdog", "sphinx", "pylons-sphinx-themes"] 146 | testing = ["watchdog", "pytest", "pytest-cov", "mock"] 147 | 148 | [[package]] 149 | name = "mccabe" 150 | version = "0.6.1" 151 | description = "McCabe checker, plugin for flake8" 152 | category = "dev" 153 | optional = false 154 | python-versions = "*" 155 | 156 | [[package]] 157 | name = "mypy-extensions" 158 | version = "0.4.3" 159 | description = "Experimental type system extensions for programs checked with the mypy typechecker." 160 | category = "dev" 161 | optional = false 162 | python-versions = "*" 163 | 164 | [[package]] 165 | name = "pathspec" 166 | version = "0.8.1" 167 | description = "Utility library for gitignore style pattern matching of file paths." 168 | category = "dev" 169 | optional = false 170 | python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*, !=3.4.*" 171 | 172 | [[package]] 173 | name = "pycodestyle" 174 | version = "2.6.0" 175 | description = "Python style guide checker" 176 | category = "dev" 177 | optional = false 178 | python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*" 179 | 180 | [[package]] 181 | name = "pyflakes" 182 | version = "2.2.0" 183 | description = "passive checker of Python programs" 184 | category = "dev" 185 | optional = false 186 | python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*" 187 | 188 | [[package]] 189 | name = "pygments" 190 | version = "2.8.0" 191 | description = "Pygments is a syntax highlighting package written in Python." 192 | category = "main" 193 | optional = false 194 | python-versions = ">=3.5" 195 | 196 | [[package]] 197 | name = "python-dateutil" 198 | version = "2.8.1" 199 | description = "Extensions to the standard Python datetime module" 200 | category = "main" 201 | optional = false 202 | python-versions = "!=3.0.*,!=3.1.*,!=3.2.*,>=2.7" 203 | 204 | [package.dependencies] 205 | six = ">=1.5" 206 | 207 | [[package]] 208 | name = "python-dotenv" 209 | version = "0.15.0" 210 | description = "Add .env support to your django/flask apps in development and deployments" 211 | category = "main" 212 | optional = false 213 | python-versions = "*" 214 | 215 | [package.extras] 216 | cli = ["click (>=5.0)"] 217 | 218 | [[package]] 219 | name = "python-multipart" 220 | version = "0.0.5" 221 | description = "A streaming multipart parser for Python" 222 | category = "main" 223 | optional = false 224 | python-versions = "*" 225 | 226 | [package.dependencies] 227 | six = ">=1.4.0" 228 | 229 | [[package]] 230 | name = "pytz" 231 | version = "2021.1" 232 | description = "World timezone definitions, modern and historical" 233 | category = "main" 234 | optional = false 235 | python-versions = "*" 236 | 237 | [[package]] 238 | name = "pyyaml" 239 | version = "5.4.1" 240 | description = "YAML parser and emitter for Python" 241 | category = "main" 242 | optional = false 243 | python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*, !=3.4.*, !=3.5.*" 244 | 245 | [[package]] 246 | name = "regex" 247 | version = "2020.11.13" 248 | description = "Alternative regular expression module, to replace re." 249 | category = "dev" 250 | optional = false 251 | python-versions = "*" 252 | 253 | [[package]] 254 | name = "six" 255 | version = "1.15.0" 256 | description = "Python 2 and 3 compatibility utilities" 257 | category = "main" 258 | optional = false 259 | python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*" 260 | 261 | [[package]] 262 | name = "sqlparse" 263 | version = "0.4.1" 264 | description = "A non-validating SQL parser." 265 | category = "main" 266 | optional = false 267 | python-versions = ">=3.5" 268 | 269 | [[package]] 270 | name = "starlette" 271 | version = "0.14.2" 272 | description = "The little ASGI library that shines." 273 | category = "main" 274 | optional = false 275 | python-versions = ">=3.6" 276 | 277 | [package.extras] 278 | full = ["aiofiles", "graphene", "itsdangerous", "jinja2", "python-multipart", "pyyaml", "requests"] 279 | 280 | [[package]] 281 | name = "strawberry-graphql" 282 | version = "0.46.0" 283 | description = "A library for creating GraphQL APIs" 284 | category = "main" 285 | optional = false 286 | python-versions = ">=3.7,<4.0" 287 | 288 | [package.dependencies] 289 | cached-property = ">=1.5.2,<2.0.0" 290 | click = ">=7.0,<8.0" 291 | graphql-core = ">=3.1.0,<4.0.0" 292 | hupper = ">=1.5,<2.0" 293 | pygments = ">=2.3,<3.0" 294 | python-dateutil = ">=2.7.0,<3.0.0" 295 | python-multipart = ">=0.0.5,<0.0.6" 296 | starlette = ">=0.13.6,<0.15.0" 297 | typing_extensions = ">=3.7.4,<4.0.0" 298 | 299 | [package.extras] 300 | debug-server = ["uvicorn (>=0.11.6,<0.14.0)"] 301 | django = ["django (>=2,<4)", "asgiref (>=3.2,<4.0)"] 302 | flask = ["flask (>=1.1,<2.0)"] 303 | opentelemetry = ["opentelemetry-api (>=0.17b0,<0.18)", "opentelemetry-sdk (>=0.17b0,<0.18)"] 304 | pydantic = ["pydantic (>=1.6.1,<2.0.0)"] 305 | 306 | [[package]] 307 | name = "toml" 308 | version = "0.10.2" 309 | description = "Python Library for Tom's Obvious, Minimal Language" 310 | category = "dev" 311 | optional = false 312 | python-versions = ">=2.6, !=3.0.*, !=3.1.*, !=3.2.*" 313 | 314 | [[package]] 315 | name = "typed-ast" 316 | version = "1.4.2" 317 | description = "a fork of Python 2 and 3 ast modules with type comment support" 318 | category = "dev" 319 | optional = false 320 | python-versions = "*" 321 | 322 | [[package]] 323 | name = "typing-extensions" 324 | version = "3.7.4.3" 325 | description = "Backported and Experimental Type Hints for Python 3.5+" 326 | category = "main" 327 | optional = false 328 | python-versions = "*" 329 | 330 | [[package]] 331 | name = "uvicorn" 332 | version = "0.13.4" 333 | description = "The lightning-fast ASGI server." 334 | category = "main" 335 | optional = false 336 | python-versions = "*" 337 | 338 | [package.dependencies] 339 | click = ">=7.0.0,<8.0.0" 340 | colorama = {version = ">=0.4", optional = true, markers = "sys_platform == \"win32\" and extra == \"standard\""} 341 | h11 = ">=0.8" 342 | httptools = {version = ">=0.1.0,<0.2.0", optional = true, markers = "sys_platform != \"win32\" and sys_platform != \"cygwin\" and platform_python_implementation != \"PyPy\" and extra == \"standard\""} 343 | python-dotenv = {version = ">=0.13", optional = true, markers = "extra == \"standard\""} 344 | PyYAML = {version = ">=5.1", optional = true, markers = "extra == \"standard\""} 345 | uvloop = {version = ">=0.14.0,<0.15.0 || >0.15.0,<0.15.1 || >0.15.1", optional = true, markers = "sys_platform != \"win32\" and sys_platform != \"cygwin\" and platform_python_implementation != \"PyPy\" and extra == \"standard\""} 346 | watchgod = {version = ">=0.6", optional = true, markers = "extra == \"standard\""} 347 | websockets = {version = ">=8.0.0,<9.0.0", optional = true, markers = "extra == \"standard\""} 348 | 349 | [package.extras] 350 | standard = ["websockets (>=8.0.0,<9.0.0)", "watchgod (>=0.6)", "python-dotenv (>=0.13)", "PyYAML (>=5.1)", "httptools (>=0.1.0,<0.2.0)", "uvloop (>=0.14.0,!=0.15.0,!=0.15.1)", "colorama (>=0.4)"] 351 | 352 | [[package]] 353 | name = "uvloop" 354 | version = "0.15.2" 355 | description = "Fast implementation of asyncio event loop on top of libuv" 356 | category = "main" 357 | optional = false 358 | python-versions = ">=3.7" 359 | 360 | [package.extras] 361 | dev = ["Cython (>=0.29.20,<0.30.0)", "pytest (>=3.6.0)", "Sphinx (>=1.7.3,<1.8.0)", "sphinxcontrib-asyncio (>=0.2.0,<0.3.0)", "sphinx-rtd-theme (>=0.2.4,<0.3.0)", "aiohttp", "flake8 (>=3.8.4,<3.9.0)", "psutil", "pycodestyle (>=2.6.0,<2.7.0)", "pyOpenSSL (>=19.0.0,<19.1.0)", "mypy (>=0.800)"] 362 | docs = ["Sphinx (>=1.7.3,<1.8.0)", "sphinxcontrib-asyncio (>=0.2.0,<0.3.0)", "sphinx-rtd-theme (>=0.2.4,<0.3.0)"] 363 | test = ["aiohttp", "flake8 (>=3.8.4,<3.9.0)", "psutil", "pycodestyle (>=2.6.0,<2.7.0)", "pyOpenSSL (>=19.0.0,<19.1.0)", "mypy (>=0.800)"] 364 | 365 | [[package]] 366 | name = "watchgod" 367 | version = "0.7" 368 | description = "Simple, modern file watching and code reload in python." 369 | category = "main" 370 | optional = false 371 | python-versions = ">=3.5" 372 | 373 | [[package]] 374 | name = "websockets" 375 | version = "8.1" 376 | description = "An implementation of the WebSocket Protocol (RFC 6455 & 7692)" 377 | category = "main" 378 | optional = false 379 | python-versions = ">=3.6.1" 380 | 381 | [metadata] 382 | lock-version = "1.1" 383 | python-versions = "^3.9" 384 | content-hash = "e06b74c9417edea6ef3cae95a8aa83dac8e481473bbb725f9811bb78faade27e" 385 | 386 | [metadata.files] 387 | appdirs = [ 388 | {file = "appdirs-1.4.4-py2.py3-none-any.whl", hash = "sha256:a841dacd6b99318a741b166adb07e19ee71a274450e68237b4650ca1055ab128"}, 389 | {file = "appdirs-1.4.4.tar.gz", hash = "sha256:7d5d0167b2b1ba821647616af46a749d1c653740dd0d2415100fe26e27afdf41"}, 390 | ] 391 | asgiref = [ 392 | {file = "asgiref-3.3.1-py3-none-any.whl", hash = "sha256:5ee950735509d04eb673bd7f7120f8fa1c9e2df495394992c73234d526907e17"}, 393 | {file = "asgiref-3.3.1.tar.gz", hash = "sha256:7162a3cb30ab0609f1a4c95938fd73e8604f63bdba516a7f7d64b83ff09478f0"}, 394 | ] 395 | black = [ 396 | {file = "black-20.8b1-py3-none-any.whl", hash = "sha256:70b62ef1527c950db59062cda342ea224d772abdf6adc58b86a45421bab20a6b"}, 397 | {file = "black-20.8b1.tar.gz", hash = "sha256:1c02557aa099101b9d21496f8a914e9ed2222ef70336404eeeac8edba836fbea"}, 398 | ] 399 | broadcaster = [ 400 | {file = "broadcaster-0.2.0-py3-none-any.whl", hash = "sha256:50f93d1af7e9097a87ef3b2da269b4b4c5630ec080dc5c7f941ef314291937b1"}, 401 | {file = "broadcaster-0.2.0.tar.gz", hash = "sha256:72056f9b77b091dd4bbad4d7484bd0e6835c3443d4564d0bbf41190c29c606c6"}, 402 | ] 403 | cached-property = [ 404 | {file = "cached-property-1.5.2.tar.gz", hash = "sha256:9fa5755838eecbb2d234c3aa390bd80fbd3ac6b6869109bfc1b499f7bd89a130"}, 405 | {file = "cached_property-1.5.2-py2.py3-none-any.whl", hash = "sha256:df4f613cf7ad9a588cc381aaf4a512d26265ecebd5eb9e1ba12f1319eb85a6a0"}, 406 | ] 407 | click = [ 408 | {file = "click-7.1.2-py2.py3-none-any.whl", hash = "sha256:dacca89f4bfadd5de3d7489b7c8a566eee0d3676333fbb50030263894c38c0dc"}, 409 | {file = "click-7.1.2.tar.gz", hash = "sha256:d2b5255c7c6349bc1bd1e59e08cd12acbbd63ce649f2588755783aa94dfb6b1a"}, 410 | ] 411 | colorama = [ 412 | {file = "colorama-0.4.4-py2.py3-none-any.whl", hash = "sha256:9f47eda37229f68eee03b24b9748937c7dc3868f906e8ba69fbcbdd3bc5dc3e2"}, 413 | {file = "colorama-0.4.4.tar.gz", hash = "sha256:5941b2b48a20143d2267e95b1c2a7603ce057ee39fd88e7329b0c292aa16869b"}, 414 | ] 415 | django = [ 416 | {file = "Django-3.1.7-py3-none-any.whl", hash = "sha256:baf099db36ad31f970775d0be5587cc58a6256a6771a44eb795b554d45f211b8"}, 417 | {file = "Django-3.1.7.tar.gz", hash = "sha256:32ce792ee9b6a0cbbec340123e229ac9f765dff8c2a4ae9247a14b2ba3a365a7"}, 418 | ] 419 | flake8 = [ 420 | {file = "flake8-3.8.4-py2.py3-none-any.whl", hash = "sha256:749dbbd6bfd0cf1318af27bf97a14e28e5ff548ef8e5b1566ccfb25a11e7c839"}, 421 | {file = "flake8-3.8.4.tar.gz", hash = "sha256:aadae8761ec651813c24be05c6f7b4680857ef6afaae4651a4eccaef97ce6c3b"}, 422 | ] 423 | graphql-core = [ 424 | {file = "graphql-core-3.1.3.tar.gz", hash = "sha256:db599b57b0f7dc13541922a83b30192be573b7143330ef3613813942ce4073a0"}, 425 | {file = "graphql_core-3.1.3-py3-none-any.whl", hash = "sha256:95b0d6510bb5532dcac5927f5dfd674a580b33d6ba6417c3dc75086d9a210c83"}, 426 | ] 427 | h11 = [ 428 | {file = "h11-0.12.0-py3-none-any.whl", hash = "sha256:36a3cb8c0a032f56e2da7084577878a035d3b61d104230d4bd49c0c6b555a9c6"}, 429 | {file = "h11-0.12.0.tar.gz", hash = "sha256:47222cb6067e4a307d535814917cd98fd0a57b6788ce715755fa2b6c28b56042"}, 430 | ] 431 | httptools = [ 432 | {file = "httptools-0.1.1-cp35-cp35m-macosx_10_13_x86_64.whl", hash = "sha256:a2719e1d7a84bb131c4f1e0cb79705034b48de6ae486eb5297a139d6a3296dce"}, 433 | {file = "httptools-0.1.1-cp35-cp35m-manylinux1_x86_64.whl", hash = "sha256:fa3cd71e31436911a44620473e873a256851e1f53dee56669dae403ba41756a4"}, 434 | {file = "httptools-0.1.1-cp36-cp36m-macosx_10_13_x86_64.whl", hash = "sha256:86c6acd66765a934e8730bf0e9dfaac6fdcf2a4334212bd4a0a1c78f16475ca6"}, 435 | {file = "httptools-0.1.1-cp36-cp36m-manylinux1_x86_64.whl", hash = "sha256:bc3114b9edbca5a1eb7ae7db698c669eb53eb8afbbebdde116c174925260849c"}, 436 | {file = "httptools-0.1.1-cp36-cp36m-win_amd64.whl", hash = "sha256:ac0aa11e99454b6a66989aa2d44bca41d4e0f968e395a0a8f164b401fefe359a"}, 437 | {file = "httptools-0.1.1-cp37-cp37m-macosx_10_13_x86_64.whl", hash = "sha256:96da81e1992be8ac2fd5597bf0283d832287e20cb3cfde8996d2b00356d4e17f"}, 438 | {file = "httptools-0.1.1-cp37-cp37m-manylinux1_x86_64.whl", hash = "sha256:56b6393c6ac7abe632f2294da53f30d279130a92e8ae39d8d14ee2e1b05ad1f2"}, 439 | {file = "httptools-0.1.1-cp37-cp37m-win_amd64.whl", hash = "sha256:96eb359252aeed57ea5c7b3d79839aaa0382c9d3149f7d24dd7172b1bcecb009"}, 440 | {file = "httptools-0.1.1-cp38-cp38-macosx_10_13_x86_64.whl", hash = "sha256:fea04e126014169384dee76a153d4573d90d0cbd1d12185da089f73c78390437"}, 441 | {file = "httptools-0.1.1-cp38-cp38-manylinux1_x86_64.whl", hash = "sha256:3592e854424ec94bd17dc3e0c96a64e459ec4147e6d53c0a42d0ebcef9cb9c5d"}, 442 | {file = "httptools-0.1.1-cp38-cp38-win_amd64.whl", hash = "sha256:0a4b1b2012b28e68306575ad14ad5e9120b34fccd02a81eb08838d7e3bbb48be"}, 443 | {file = "httptools-0.1.1.tar.gz", hash = "sha256:41b573cf33f64a8f8f3400d0a7faf48e1888582b6f6e02b82b9bd4f0bf7497ce"}, 444 | ] 445 | hupper = [ 446 | {file = "hupper-1.10.2-py2.py3-none-any.whl", hash = "sha256:5de835f3b58324af2a8a16f52270c4d1a3d1734c45eed94b77fd622aea737f29"}, 447 | {file = "hupper-1.10.2.tar.gz", hash = "sha256:3818f53dabc24da66f65cf4878c1c7a9b5df0c46b813e014abdd7c569eb9a02a"}, 448 | ] 449 | mccabe = [ 450 | {file = "mccabe-0.6.1-py2.py3-none-any.whl", hash = "sha256:ab8a6258860da4b6677da4bd2fe5dc2c659cff31b3ee4f7f5d64e79735b80d42"}, 451 | {file = "mccabe-0.6.1.tar.gz", hash = "sha256:dd8d182285a0fe56bace7f45b5e7d1a6ebcbf524e8f3bd87eb0f125271b8831f"}, 452 | ] 453 | mypy-extensions = [ 454 | {file = "mypy_extensions-0.4.3-py2.py3-none-any.whl", hash = "sha256:090fedd75945a69ae91ce1303b5824f428daf5a028d2f6ab8a299250a846f15d"}, 455 | {file = "mypy_extensions-0.4.3.tar.gz", hash = "sha256:2d82818f5bb3e369420cb3c4060a7970edba416647068eb4c5343488a6c604a8"}, 456 | ] 457 | pathspec = [ 458 | {file = "pathspec-0.8.1-py2.py3-none-any.whl", hash = "sha256:aa0cb481c4041bf52ffa7b0d8fa6cd3e88a2ca4879c533c9153882ee2556790d"}, 459 | {file = "pathspec-0.8.1.tar.gz", hash = "sha256:86379d6b86d75816baba717e64b1a3a3469deb93bb76d613c9ce79edc5cb68fd"}, 460 | ] 461 | pycodestyle = [ 462 | {file = "pycodestyle-2.6.0-py2.py3-none-any.whl", hash = "sha256:2295e7b2f6b5bd100585ebcb1f616591b652db8a741695b3d8f5d28bdc934367"}, 463 | {file = "pycodestyle-2.6.0.tar.gz", hash = "sha256:c58a7d2815e0e8d7972bf1803331fb0152f867bd89adf8a01dfd55085434192e"}, 464 | ] 465 | pyflakes = [ 466 | {file = "pyflakes-2.2.0-py2.py3-none-any.whl", hash = "sha256:0d94e0e05a19e57a99444b6ddcf9a6eb2e5c68d3ca1e98e90707af8152c90a92"}, 467 | {file = "pyflakes-2.2.0.tar.gz", hash = "sha256:35b2d75ee967ea93b55750aa9edbbf72813e06a66ba54438df2cfac9e3c27fc8"}, 468 | ] 469 | pygments = [ 470 | {file = "Pygments-2.8.0-py3-none-any.whl", hash = "sha256:b21b072d0ccdf29297a82a2363359d99623597b8a265b8081760e4d0f7153c88"}, 471 | {file = "Pygments-2.8.0.tar.gz", hash = "sha256:37a13ba168a02ac54cc5891a42b1caec333e59b66addb7fa633ea8a6d73445c0"}, 472 | ] 473 | python-dateutil = [ 474 | {file = "python-dateutil-2.8.1.tar.gz", hash = "sha256:73ebfe9dbf22e832286dafa60473e4cd239f8592f699aa5adaf10050e6e1823c"}, 475 | {file = "python_dateutil-2.8.1-py2.py3-none-any.whl", hash = "sha256:75bb3f31ea686f1197762692a9ee6a7550b59fc6ca3a1f4b5d7e32fb98e2da2a"}, 476 | ] 477 | python-dotenv = [ 478 | {file = "python-dotenv-0.15.0.tar.gz", hash = "sha256:587825ed60b1711daea4832cf37524dfd404325b7db5e25ebe88c495c9f807a0"}, 479 | {file = "python_dotenv-0.15.0-py2.py3-none-any.whl", hash = "sha256:0c8d1b80d1a1e91717ea7d526178e3882732420b03f08afea0406db6402e220e"}, 480 | ] 481 | python-multipart = [ 482 | {file = "python-multipart-0.0.5.tar.gz", hash = "sha256:f7bb5f611fc600d15fa47b3974c8aa16e93724513b49b5f95c81e6624c83fa43"}, 483 | ] 484 | pytz = [ 485 | {file = "pytz-2021.1-py2.py3-none-any.whl", hash = "sha256:eb10ce3e7736052ed3623d49975ce333bcd712c7bb19a58b9e2089d4057d0798"}, 486 | {file = "pytz-2021.1.tar.gz", hash = "sha256:83a4a90894bf38e243cf052c8b58f381bfe9a7a483f6a9cab140bc7f702ac4da"}, 487 | ] 488 | pyyaml = [ 489 | {file = "PyYAML-5.4.1-cp27-cp27m-macosx_10_9_x86_64.whl", hash = "sha256:3b2b1824fe7112845700f815ff6a489360226a5609b96ec2190a45e62a9fc922"}, 490 | {file = "PyYAML-5.4.1-cp27-cp27m-win32.whl", hash = "sha256:129def1b7c1bf22faffd67b8f3724645203b79d8f4cc81f674654d9902cb4393"}, 491 | {file = "PyYAML-5.4.1-cp27-cp27m-win_amd64.whl", hash = "sha256:4465124ef1b18d9ace298060f4eccc64b0850899ac4ac53294547536533800c8"}, 492 | {file = "PyYAML-5.4.1-cp27-cp27mu-manylinux1_x86_64.whl", hash = "sha256:bb4191dfc9306777bc594117aee052446b3fa88737cd13b7188d0e7aa8162185"}, 493 | {file = "PyYAML-5.4.1-cp36-cp36m-macosx_10_9_x86_64.whl", hash = "sha256:6c78645d400265a062508ae399b60b8c167bf003db364ecb26dcab2bda048253"}, 494 | {file = "PyYAML-5.4.1-cp36-cp36m-manylinux1_x86_64.whl", hash = "sha256:4e0583d24c881e14342eaf4ec5fbc97f934b999a6828693a99157fde912540cc"}, 495 | {file = "PyYAML-5.4.1-cp36-cp36m-win32.whl", hash = "sha256:3bd0e463264cf257d1ffd2e40223b197271046d09dadf73a0fe82b9c1fc385a5"}, 496 | {file = "PyYAML-5.4.1-cp36-cp36m-win_amd64.whl", hash = "sha256:e4fac90784481d221a8e4b1162afa7c47ed953be40d31ab4629ae917510051df"}, 497 | {file = "PyYAML-5.4.1-cp37-cp37m-macosx_10_9_x86_64.whl", hash = "sha256:5accb17103e43963b80e6f837831f38d314a0495500067cb25afab2e8d7a4018"}, 498 | {file = "PyYAML-5.4.1-cp37-cp37m-manylinux1_x86_64.whl", hash = "sha256:e1d4970ea66be07ae37a3c2e48b5ec63f7ba6804bdddfdbd3cfd954d25a82e63"}, 499 | {file = "PyYAML-5.4.1-cp37-cp37m-win32.whl", hash = "sha256:dd5de0646207f053eb0d6c74ae45ba98c3395a571a2891858e87df7c9b9bd51b"}, 500 | {file = "PyYAML-5.4.1-cp37-cp37m-win_amd64.whl", hash = "sha256:08682f6b72c722394747bddaf0aa62277e02557c0fd1c42cb853016a38f8dedf"}, 501 | {file = "PyYAML-5.4.1-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:d2d9808ea7b4af864f35ea216be506ecec180628aced0704e34aca0b040ffe46"}, 502 | {file = "PyYAML-5.4.1-cp38-cp38-manylinux1_x86_64.whl", hash = "sha256:8c1be557ee92a20f184922c7b6424e8ab6691788e6d86137c5d93c1a6ec1b8fb"}, 503 | {file = "PyYAML-5.4.1-cp38-cp38-win32.whl", hash = "sha256:fa5ae20527d8e831e8230cbffd9f8fe952815b2b7dae6ffec25318803a7528fc"}, 504 | {file = "PyYAML-5.4.1-cp38-cp38-win_amd64.whl", hash = "sha256:0f5f5786c0e09baddcd8b4b45f20a7b5d61a7e7e99846e3c799b05c7c53fa696"}, 505 | {file = "PyYAML-5.4.1-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:294db365efa064d00b8d1ef65d8ea2c3426ac366c0c4368d930bf1c5fb497f77"}, 506 | {file = "PyYAML-5.4.1-cp39-cp39-manylinux1_x86_64.whl", hash = "sha256:74c1485f7707cf707a7aef42ef6322b8f97921bd89be2ab6317fd782c2d53183"}, 507 | {file = "PyYAML-5.4.1-cp39-cp39-win32.whl", hash = "sha256:49d4cdd9065b9b6e206d0595fee27a96b5dd22618e7520c33204a4a3239d5b10"}, 508 | {file = "PyYAML-5.4.1-cp39-cp39-win_amd64.whl", hash = "sha256:c20cfa2d49991c8b4147af39859b167664f2ad4561704ee74c1de03318e898db"}, 509 | {file = "PyYAML-5.4.1.tar.gz", hash = "sha256:607774cbba28732bfa802b54baa7484215f530991055bb562efbed5b2f20a45e"}, 510 | ] 511 | regex = [ 512 | {file = "regex-2020.11.13-cp36-cp36m-macosx_10_9_x86_64.whl", hash = "sha256:8b882a78c320478b12ff024e81dc7d43c1462aa4a3341c754ee65d857a521f85"}, 513 | {file = "regex-2020.11.13-cp36-cp36m-manylinux1_i686.whl", hash = "sha256:a63f1a07932c9686d2d416fb295ec2c01ab246e89b4d58e5fa468089cab44b70"}, 514 | {file = "regex-2020.11.13-cp36-cp36m-manylinux1_x86_64.whl", hash = "sha256:6e4b08c6f8daca7d8f07c8d24e4331ae7953333dbd09c648ed6ebd24db5a10ee"}, 515 | {file = "regex-2020.11.13-cp36-cp36m-manylinux2010_i686.whl", hash = "sha256:bba349276b126947b014e50ab3316c027cac1495992f10e5682dc677b3dfa0c5"}, 516 | {file = "regex-2020.11.13-cp36-cp36m-manylinux2010_x86_64.whl", hash = "sha256:56e01daca75eae420bce184edd8bb341c8eebb19dd3bce7266332258f9fb9dd7"}, 517 | {file = "regex-2020.11.13-cp36-cp36m-manylinux2014_aarch64.whl", hash = "sha256:6a8ce43923c518c24a2579fda49f093f1397dad5d18346211e46f134fc624e31"}, 518 | {file = "regex-2020.11.13-cp36-cp36m-manylinux2014_i686.whl", hash = "sha256:1ab79fcb02b930de09c76d024d279686ec5d532eb814fd0ed1e0051eb8bd2daa"}, 519 | {file = "regex-2020.11.13-cp36-cp36m-manylinux2014_x86_64.whl", hash = "sha256:9801c4c1d9ae6a70aeb2128e5b4b68c45d4f0af0d1535500884d644fa9b768c6"}, 520 | {file = "regex-2020.11.13-cp36-cp36m-win32.whl", hash = "sha256:49cae022fa13f09be91b2c880e58e14b6da5d10639ed45ca69b85faf039f7a4e"}, 521 | {file = "regex-2020.11.13-cp36-cp36m-win_amd64.whl", hash = "sha256:749078d1eb89484db5f34b4012092ad14b327944ee7f1c4f74d6279a6e4d1884"}, 522 | {file = "regex-2020.11.13-cp37-cp37m-macosx_10_9_x86_64.whl", hash = "sha256:b2f4007bff007c96a173e24dcda236e5e83bde4358a557f9ccf5e014439eae4b"}, 523 | {file = "regex-2020.11.13-cp37-cp37m-manylinux1_i686.whl", hash = "sha256:38c8fd190db64f513fe4e1baa59fed086ae71fa45083b6936b52d34df8f86a88"}, 524 | {file = "regex-2020.11.13-cp37-cp37m-manylinux1_x86_64.whl", hash = "sha256:5862975b45d451b6db51c2e654990c1820523a5b07100fc6903e9c86575202a0"}, 525 | {file = "regex-2020.11.13-cp37-cp37m-manylinux2010_i686.whl", hash = "sha256:262c6825b309e6485ec2493ffc7e62a13cf13fb2a8b6d212f72bd53ad34118f1"}, 526 | {file = "regex-2020.11.13-cp37-cp37m-manylinux2010_x86_64.whl", hash = "sha256:bafb01b4688833e099d79e7efd23f99172f501a15c44f21ea2118681473fdba0"}, 527 | {file = "regex-2020.11.13-cp37-cp37m-manylinux2014_aarch64.whl", hash = "sha256:e32f5f3d1b1c663af7f9c4c1e72e6ffe9a78c03a31e149259f531e0fed826512"}, 528 | {file = "regex-2020.11.13-cp37-cp37m-manylinux2014_i686.whl", hash = "sha256:3bddc701bdd1efa0d5264d2649588cbfda549b2899dc8d50417e47a82e1387ba"}, 529 | {file = "regex-2020.11.13-cp37-cp37m-manylinux2014_x86_64.whl", hash = "sha256:02951b7dacb123d8ea6da44fe45ddd084aa6777d4b2454fa0da61d569c6fa538"}, 530 | {file = "regex-2020.11.13-cp37-cp37m-win32.whl", hash = "sha256:0d08e71e70c0237883d0bef12cad5145b84c3705e9c6a588b2a9c7080e5af2a4"}, 531 | {file = "regex-2020.11.13-cp37-cp37m-win_amd64.whl", hash = "sha256:1fa7ee9c2a0e30405e21031d07d7ba8617bc590d391adfc2b7f1e8b99f46f444"}, 532 | {file = "regex-2020.11.13-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:baf378ba6151f6e272824b86a774326f692bc2ef4cc5ce8d5bc76e38c813a55f"}, 533 | {file = "regex-2020.11.13-cp38-cp38-manylinux1_i686.whl", hash = "sha256:e3faaf10a0d1e8e23a9b51d1900b72e1635c2d5b0e1bea1c18022486a8e2e52d"}, 534 | {file = "regex-2020.11.13-cp38-cp38-manylinux1_x86_64.whl", hash = "sha256:2a11a3e90bd9901d70a5b31d7dd85114755a581a5da3fc996abfefa48aee78af"}, 535 | {file = "regex-2020.11.13-cp38-cp38-manylinux2010_i686.whl", hash = "sha256:d1ebb090a426db66dd80df8ca85adc4abfcbad8a7c2e9a5ec7513ede522e0a8f"}, 536 | {file = "regex-2020.11.13-cp38-cp38-manylinux2010_x86_64.whl", hash = "sha256:b2b1a5ddae3677d89b686e5c625fc5547c6e492bd755b520de5332773a8af06b"}, 537 | {file = "regex-2020.11.13-cp38-cp38-manylinux2014_aarch64.whl", hash = "sha256:2c99e97d388cd0a8d30f7c514d67887d8021541b875baf09791a3baad48bb4f8"}, 538 | {file = "regex-2020.11.13-cp38-cp38-manylinux2014_i686.whl", hash = "sha256:c084582d4215593f2f1d28b65d2a2f3aceff8342aa85afd7be23a9cad74a0de5"}, 539 | {file = "regex-2020.11.13-cp38-cp38-manylinux2014_x86_64.whl", hash = "sha256:a3d748383762e56337c39ab35c6ed4deb88df5326f97a38946ddd19028ecce6b"}, 540 | {file = "regex-2020.11.13-cp38-cp38-win32.whl", hash = "sha256:7913bd25f4ab274ba37bc97ad0e21c31004224ccb02765ad984eef43e04acc6c"}, 541 | {file = "regex-2020.11.13-cp38-cp38-win_amd64.whl", hash = "sha256:6c54ce4b5d61a7129bad5c5dc279e222afd00e721bf92f9ef09e4fae28755683"}, 542 | {file = "regex-2020.11.13-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:1862a9d9194fae76a7aaf0150d5f2a8ec1da89e8b55890b1786b8f88a0f619dc"}, 543 | {file = "regex-2020.11.13-cp39-cp39-manylinux1_i686.whl", hash = "sha256:4902e6aa086cbb224241adbc2f06235927d5cdacffb2425c73e6570e8d862364"}, 544 | {file = "regex-2020.11.13-cp39-cp39-manylinux1_x86_64.whl", hash = "sha256:7a25fcbeae08f96a754b45bdc050e1fb94b95cab046bf56b016c25e9ab127b3e"}, 545 | {file = "regex-2020.11.13-cp39-cp39-manylinux2010_i686.whl", hash = "sha256:d2d8ce12b7c12c87e41123997ebaf1a5767a5be3ec545f64675388970f415e2e"}, 546 | {file = "regex-2020.11.13-cp39-cp39-manylinux2010_x86_64.whl", hash = "sha256:f7d29a6fc4760300f86ae329e3b6ca28ea9c20823df123a2ea8693e967b29917"}, 547 | {file = "regex-2020.11.13-cp39-cp39-manylinux2014_aarch64.whl", hash = "sha256:717881211f46de3ab130b58ec0908267961fadc06e44f974466d1887f865bd5b"}, 548 | {file = "regex-2020.11.13-cp39-cp39-manylinux2014_i686.whl", hash = "sha256:3128e30d83f2e70b0bed9b2a34e92707d0877e460b402faca908c6667092ada9"}, 549 | {file = "regex-2020.11.13-cp39-cp39-manylinux2014_x86_64.whl", hash = "sha256:8f6a2229e8ad946e36815f2a03386bb8353d4bde368fdf8ca5f0cb97264d3b5c"}, 550 | {file = "regex-2020.11.13-cp39-cp39-win32.whl", hash = "sha256:f8f295db00ef5f8bae530fc39af0b40486ca6068733fb860b42115052206466f"}, 551 | {file = "regex-2020.11.13-cp39-cp39-win_amd64.whl", hash = "sha256:a15f64ae3a027b64496a71ab1f722355e570c3fac5ba2801cafce846bf5af01d"}, 552 | {file = "regex-2020.11.13.tar.gz", hash = "sha256:83d6b356e116ca119db8e7c6fc2983289d87b27b3fac238cfe5dca529d884562"}, 553 | ] 554 | six = [ 555 | {file = "six-1.15.0-py2.py3-none-any.whl", hash = "sha256:8b74bedcbbbaca38ff6d7491d76f2b06b3592611af620f8426e82dddb04a5ced"}, 556 | {file = "six-1.15.0.tar.gz", hash = "sha256:30639c035cdb23534cd4aa2dd52c3bf48f06e5f4a941509c8bafd8ce11080259"}, 557 | ] 558 | sqlparse = [ 559 | {file = "sqlparse-0.4.1-py3-none-any.whl", hash = "sha256:017cde379adbd6a1f15a61873f43e8274179378e95ef3fede90b5aa64d304ed0"}, 560 | {file = "sqlparse-0.4.1.tar.gz", hash = "sha256:0f91fd2e829c44362cbcfab3e9ae12e22badaa8a29ad5ff599f9ec109f0454e8"}, 561 | ] 562 | starlette = [ 563 | {file = "starlette-0.14.2-py3-none-any.whl", hash = "sha256:3c8e48e52736b3161e34c9f0e8153b4f32ec5d8995a3ee1d59410d92f75162ed"}, 564 | {file = "starlette-0.14.2.tar.gz", hash = "sha256:7d49f4a27f8742262ef1470608c59ddbc66baf37c148e938c7038e6bc7a998aa"}, 565 | ] 566 | strawberry-graphql = [ 567 | {file = "strawberry-graphql-0.46.0.tar.gz", hash = "sha256:d11714ba51dc36abc31dc7763607b606ea4250f2c1bedd53613d1f9e07dcb962"}, 568 | {file = "strawberry_graphql-0.46.0-py3-none-any.whl", hash = "sha256:630a539e426c49b3de1c09a2a28401ab4fe5de0d5f1ef6c0ded9cd02e0a24435"}, 569 | ] 570 | toml = [ 571 | {file = "toml-0.10.2-py2.py3-none-any.whl", hash = "sha256:806143ae5bfb6a3c6e736a764057db0e6a0e05e338b5630894a5f779cabb4f9b"}, 572 | {file = "toml-0.10.2.tar.gz", hash = "sha256:b3bda1d108d5dd99f4a20d24d9c348e91c4db7ab1b749200bded2f839ccbe68f"}, 573 | ] 574 | typed-ast = [ 575 | {file = "typed_ast-1.4.2-cp35-cp35m-manylinux1_i686.whl", hash = "sha256:7703620125e4fb79b64aa52427ec192822e9f45d37d4b6625ab37ef403e1df70"}, 576 | {file = "typed_ast-1.4.2-cp35-cp35m-manylinux1_x86_64.whl", hash = "sha256:c9aadc4924d4b5799112837b226160428524a9a45f830e0d0f184b19e4090487"}, 577 | {file = "typed_ast-1.4.2-cp35-cp35m-manylinux2014_aarch64.whl", hash = "sha256:9ec45db0c766f196ae629e509f059ff05fc3148f9ffd28f3cfe75d4afb485412"}, 578 | {file = "typed_ast-1.4.2-cp35-cp35m-win32.whl", hash = "sha256:85f95aa97a35bdb2f2f7d10ec5bbdac0aeb9dafdaf88e17492da0504de2e6400"}, 579 | {file = "typed_ast-1.4.2-cp35-cp35m-win_amd64.whl", hash = "sha256:9044ef2df88d7f33692ae3f18d3be63dec69c4fb1b5a4a9ac950f9b4ba571606"}, 580 | {file = "typed_ast-1.4.2-cp36-cp36m-macosx_10_9_x86_64.whl", hash = "sha256:c1c876fd795b36126f773db9cbb393f19808edd2637e00fd6caba0e25f2c7b64"}, 581 | {file = "typed_ast-1.4.2-cp36-cp36m-manylinux1_i686.whl", hash = "sha256:5dcfc2e264bd8a1db8b11a892bd1647154ce03eeba94b461effe68790d8b8e07"}, 582 | {file = "typed_ast-1.4.2-cp36-cp36m-manylinux1_x86_64.whl", hash = "sha256:8db0e856712f79c45956da0c9a40ca4246abc3485ae0d7ecc86a20f5e4c09abc"}, 583 | {file = "typed_ast-1.4.2-cp36-cp36m-manylinux2014_aarch64.whl", hash = "sha256:d003156bb6a59cda9050e983441b7fa2487f7800d76bdc065566b7d728b4581a"}, 584 | {file = "typed_ast-1.4.2-cp36-cp36m-win32.whl", hash = "sha256:4c790331247081ea7c632a76d5b2a265e6d325ecd3179d06e9cf8d46d90dd151"}, 585 | {file = "typed_ast-1.4.2-cp36-cp36m-win_amd64.whl", hash = "sha256:d175297e9533d8d37437abc14e8a83cbc68af93cc9c1c59c2c292ec59a0697a3"}, 586 | {file = "typed_ast-1.4.2-cp37-cp37m-macosx_10_9_x86_64.whl", hash = "sha256:cf54cfa843f297991b7388c281cb3855d911137223c6b6d2dd82a47ae5125a41"}, 587 | {file = "typed_ast-1.4.2-cp37-cp37m-manylinux1_i686.whl", hash = "sha256:b4fcdcfa302538f70929eb7b392f536a237cbe2ed9cba88e3bf5027b39f5f77f"}, 588 | {file = "typed_ast-1.4.2-cp37-cp37m-manylinux1_x86_64.whl", hash = "sha256:987f15737aba2ab5f3928c617ccf1ce412e2e321c77ab16ca5a293e7bbffd581"}, 589 | {file = "typed_ast-1.4.2-cp37-cp37m-manylinux2014_aarch64.whl", hash = "sha256:37f48d46d733d57cc70fd5f30572d11ab8ed92da6e6b28e024e4a3edfb456e37"}, 590 | {file = "typed_ast-1.4.2-cp37-cp37m-win32.whl", hash = "sha256:36d829b31ab67d6fcb30e185ec996e1f72b892255a745d3a82138c97d21ed1cd"}, 591 | {file = "typed_ast-1.4.2-cp37-cp37m-win_amd64.whl", hash = "sha256:8368f83e93c7156ccd40e49a783a6a6850ca25b556c0fa0240ed0f659d2fe496"}, 592 | {file = "typed_ast-1.4.2-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:963c80b583b0661918718b095e02303d8078950b26cc00b5e5ea9ababe0de1fc"}, 593 | {file = "typed_ast-1.4.2-cp38-cp38-manylinux1_i686.whl", hash = "sha256:e683e409e5c45d5c9082dc1daf13f6374300806240719f95dc783d1fc942af10"}, 594 | {file = "typed_ast-1.4.2-cp38-cp38-manylinux1_x86_64.whl", hash = "sha256:84aa6223d71012c68d577c83f4e7db50d11d6b1399a9c779046d75e24bed74ea"}, 595 | {file = "typed_ast-1.4.2-cp38-cp38-manylinux2014_aarch64.whl", hash = "sha256:a38878a223bdd37c9709d07cd357bb79f4c760b29210e14ad0fb395294583787"}, 596 | {file = "typed_ast-1.4.2-cp38-cp38-win32.whl", hash = "sha256:a2c927c49f2029291fbabd673d51a2180038f8cd5a5b2f290f78c4516be48be2"}, 597 | {file = "typed_ast-1.4.2-cp38-cp38-win_amd64.whl", hash = "sha256:c0c74e5579af4b977c8b932f40a5464764b2f86681327410aa028a22d2f54937"}, 598 | {file = "typed_ast-1.4.2-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:07d49388d5bf7e863f7fa2f124b1b1d89d8aa0e2f7812faff0a5658c01c59aa1"}, 599 | {file = "typed_ast-1.4.2-cp39-cp39-manylinux1_i686.whl", hash = "sha256:240296b27397e4e37874abb1df2a608a92df85cf3e2a04d0d4d61055c8305ba6"}, 600 | {file = "typed_ast-1.4.2-cp39-cp39-manylinux1_x86_64.whl", hash = "sha256:d746a437cdbca200622385305aedd9aef68e8a645e385cc483bdc5e488f07166"}, 601 | {file = "typed_ast-1.4.2-cp39-cp39-manylinux2014_aarch64.whl", hash = "sha256:14bf1522cdee369e8f5581238edac09150c765ec1cb33615855889cf33dcb92d"}, 602 | {file = "typed_ast-1.4.2-cp39-cp39-win32.whl", hash = "sha256:cc7b98bf58167b7f2db91a4327da24fb93368838eb84a44c472283778fc2446b"}, 603 | {file = "typed_ast-1.4.2-cp39-cp39-win_amd64.whl", hash = "sha256:7147e2a76c75f0f64c4319886e7639e490fee87c9d25cb1d4faef1d8cf83a440"}, 604 | {file = "typed_ast-1.4.2.tar.gz", hash = "sha256:9fc0b3cb5d1720e7141d103cf4819aea239f7d136acf9ee4a69b047b7986175a"}, 605 | ] 606 | typing-extensions = [ 607 | {file = "typing_extensions-3.7.4.3-py2-none-any.whl", hash = "sha256:dafc7639cde7f1b6e1acc0f457842a83e722ccca8eef5270af2d74792619a89f"}, 608 | {file = "typing_extensions-3.7.4.3-py3-none-any.whl", hash = "sha256:7cb407020f00f7bfc3cb3e7881628838e69d8f3fcab2f64742a5e76b2f841918"}, 609 | {file = "typing_extensions-3.7.4.3.tar.gz", hash = "sha256:99d4073b617d30288f569d3f13d2bd7548c3a7e4c8de87db09a9d29bb3a4a60c"}, 610 | ] 611 | uvicorn = [ 612 | {file = "uvicorn-0.13.4-py3-none-any.whl", hash = "sha256:7587f7b08bd1efd2b9bad809a3d333e972f1d11af8a5e52a9371ee3a5de71524"}, 613 | {file = "uvicorn-0.13.4.tar.gz", hash = "sha256:3292251b3c7978e8e4a7868f4baf7f7f7bb7e40c759ecc125c37e99cdea34202"}, 614 | ] 615 | uvloop = [ 616 | {file = "uvloop-0.15.2-cp37-cp37m-macosx_10_14_x86_64.whl", hash = "sha256:19fa1d56c91341318ac5d417e7b61c56e9a41183946cc70c411341173de02c69"}, 617 | {file = "uvloop-0.15.2-cp37-cp37m-manylinux2010_x86_64.whl", hash = "sha256:e5e5f855c9bf483ee6cd1eb9a179b740de80cb0ae2988e3fa22309b78e2ea0e7"}, 618 | {file = "uvloop-0.15.2-cp37-cp37m-manylinux2014_aarch64.whl", hash = "sha256:42eda9f525a208fbc4f7cecd00fa15c57cc57646c76632b3ba2fe005004f051d"}, 619 | {file = "uvloop-0.15.2-cp38-cp38-macosx_10_14_x86_64.whl", hash = "sha256:90e56f17755e41b425ad19a08c41dc358fa7bf1226c0f8e54d4d02d556f7af7c"}, 620 | {file = "uvloop-0.15.2-cp38-cp38-manylinux2010_x86_64.whl", hash = "sha256:7ae39b11a5f4cec1432d706c21ecc62f9e04d116883178b09671aa29c46f7a47"}, 621 | {file = "uvloop-0.15.2-cp38-cp38-manylinux2014_aarch64.whl", hash = "sha256:b45218c99795803fb8bdbc9435ff7f54e3a591b44cd4c121b02fa83affb61c7c"}, 622 | {file = "uvloop-0.15.2-cp39-cp39-macosx_10_14_x86_64.whl", hash = "sha256:114543c84e95df1b4ff546e6e3a27521580466a30127f12172a3278172ad68bc"}, 623 | {file = "uvloop-0.15.2-cp39-cp39-manylinux2010_x86_64.whl", hash = "sha256:44cac8575bf168601424302045234d74e3561fbdbac39b2b54cc1d1d00b70760"}, 624 | {file = "uvloop-0.15.2-cp39-cp39-manylinux2014_aarch64.whl", hash = "sha256:6de130d0cb78985a5d080e323b86c5ecaf3af82f4890492c05981707852f983c"}, 625 | {file = "uvloop-0.15.2.tar.gz", hash = "sha256:2bb0624a8a70834e54dde8feed62ed63b50bad7a1265c40d6403a2ac447bce01"}, 626 | ] 627 | watchgod = [ 628 | {file = "watchgod-0.7-py3-none-any.whl", hash = "sha256:d6c1ea21df37847ac0537ca0d6c2f4cdf513562e95f77bb93abbcf05573407b7"}, 629 | {file = "watchgod-0.7.tar.gz", hash = "sha256:48140d62b0ebe9dd9cf8381337f06351e1f2e70b2203fa9c6eff4e572ca84f29"}, 630 | ] 631 | websockets = [ 632 | {file = "websockets-8.1-cp36-cp36m-macosx_10_6_intel.whl", hash = "sha256:3762791ab8b38948f0c4d281c8b2ddfa99b7e510e46bd8dfa942a5fff621068c"}, 633 | {file = "websockets-8.1-cp36-cp36m-manylinux1_i686.whl", hash = "sha256:3db87421956f1b0779a7564915875ba774295cc86e81bc671631379371af1170"}, 634 | {file = "websockets-8.1-cp36-cp36m-manylinux1_x86_64.whl", hash = "sha256:4f9f7d28ce1d8f1295717c2c25b732c2bc0645db3215cf757551c392177d7cb8"}, 635 | {file = "websockets-8.1-cp36-cp36m-manylinux2010_i686.whl", hash = "sha256:295359a2cc78736737dd88c343cd0747546b2174b5e1adc223824bcaf3e164cb"}, 636 | {file = "websockets-8.1-cp36-cp36m-manylinux2010_x86_64.whl", hash = "sha256:1d3f1bf059d04a4e0eb4985a887d49195e15ebabc42364f4eb564b1d065793f5"}, 637 | {file = "websockets-8.1-cp36-cp36m-win32.whl", hash = "sha256:2db62a9142e88535038a6bcfea70ef9447696ea77891aebb730a333a51ed559a"}, 638 | {file = "websockets-8.1-cp36-cp36m-win_amd64.whl", hash = "sha256:0e4fb4de42701340bd2353bb2eee45314651caa6ccee80dbd5f5d5978888fed5"}, 639 | {file = "websockets-8.1-cp37-cp37m-macosx_10_6_intel.whl", hash = "sha256:9b248ba3dd8a03b1a10b19efe7d4f7fa41d158fdaa95e2cf65af5a7b95a4f989"}, 640 | {file = "websockets-8.1-cp37-cp37m-manylinux1_i686.whl", hash = "sha256:ce85b06a10fc65e6143518b96d3dca27b081a740bae261c2fb20375801a9d56d"}, 641 | {file = "websockets-8.1-cp37-cp37m-manylinux1_x86_64.whl", hash = "sha256:965889d9f0e2a75edd81a07592d0ced54daa5b0785f57dc429c378edbcffe779"}, 642 | {file = "websockets-8.1-cp37-cp37m-manylinux2010_i686.whl", hash = "sha256:751a556205d8245ff94aeef23546a1113b1dd4f6e4d102ded66c39b99c2ce6c8"}, 643 | {file = "websockets-8.1-cp37-cp37m-manylinux2010_x86_64.whl", hash = "sha256:3ef56fcc7b1ff90de46ccd5a687bbd13a3180132268c4254fc0fa44ecf4fc422"}, 644 | {file = "websockets-8.1-cp37-cp37m-win32.whl", hash = "sha256:7ff46d441db78241f4c6c27b3868c9ae71473fe03341340d2dfdbe8d79310acc"}, 645 | {file = "websockets-8.1-cp37-cp37m-win_amd64.whl", hash = "sha256:20891f0dddade307ffddf593c733a3fdb6b83e6f9eef85908113e628fa5a8308"}, 646 | {file = "websockets-8.1-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:c1ec8db4fac31850286b7cd3b9c0e1b944204668b8eb721674916d4e28744092"}, 647 | {file = "websockets-8.1-cp38-cp38-manylinux1_i686.whl", hash = "sha256:5c01fd846263a75bc8a2b9542606927cfad57e7282965d96b93c387622487485"}, 648 | {file = "websockets-8.1-cp38-cp38-manylinux1_x86_64.whl", hash = "sha256:9bef37ee224e104a413f0780e29adb3e514a5b698aabe0d969a6ba426b8435d1"}, 649 | {file = "websockets-8.1-cp38-cp38-manylinux2010_i686.whl", hash = "sha256:d705f8aeecdf3262379644e4b55107a3b55860eb812b673b28d0fbc347a60c55"}, 650 | {file = "websockets-8.1-cp38-cp38-manylinux2010_x86_64.whl", hash = "sha256:c8a116feafdb1f84607cb3b14aa1418424ae71fee131642fc568d21423b51824"}, 651 | {file = "websockets-8.1-cp38-cp38-win32.whl", hash = "sha256:e898a0863421650f0bebac8ba40840fc02258ef4714cb7e1fd76b6a6354bda36"}, 652 | {file = "websockets-8.1-cp38-cp38-win_amd64.whl", hash = "sha256:f8a7bff6e8664afc4e6c28b983845c5bc14965030e3fb98789734d416af77c4b"}, 653 | {file = "websockets-8.1.tar.gz", hash = "sha256:5c65d2da8c6bce0fca2528f69f44b2f977e06954c8512a952222cea50dad430f"}, 654 | ] 655 | -------------------------------------------------------------------------------- /django-subscriptions/pyproject.toml: -------------------------------------------------------------------------------- 1 | [tool.poetry] 2 | name = "django-subscriptions" 3 | version = "0.1.0" 4 | description = "" 5 | authors = ["Patrick Arminio "] 6 | license = "MIT" 7 | 8 | [tool.poetry.dependencies] 9 | python = "^3.9" 10 | strawberry-graphql = "^0.46.0" 11 | Django = "^3.1.7" 12 | uvicorn = {extras = ["standard"], version = "^0.13.4"} 13 | broadcaster = "^0.2.0" 14 | 15 | [tool.poetry.dev-dependencies] 16 | black = {version = "^20.8b1", allow-prereleases = true} 17 | flake8 = "^3.8.4" 18 | 19 | [build-system] 20 | requires = ["poetry-core>=1.0.0"] 21 | build-backend = "poetry.core.masonry.api" 22 | -------------------------------------------------------------------------------- /fastapi-sqlalchemy/.flake8: -------------------------------------------------------------------------------- 1 | [flake8] 2 | max-line-length = 89 3 | exclude=.venv,.git 4 | ignore = W503 5 | extend-ignore = 6 | # See https://github.com/PyCQA/pycodestyle/issues/373 7 | E203, 8 | -------------------------------------------------------------------------------- /fastapi-sqlalchemy/.projectroot: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/strawberry-graphql/examples/8a1cddbc41d3e7dfdcf2a6e1192b2bb730e3b7a1/fastapi-sqlalchemy/.projectroot -------------------------------------------------------------------------------- /fastapi-sqlalchemy/README.md: -------------------------------------------------------------------------------- 1 | # FastAPI + SQLAlchemy 2 | 3 | This examples shows you how to setup Strawberry with FastAPI and SQLAlchemy. It 4 | setups a GraphQL API to fetch the top rated movies from IMDB (stored in a sqlite 5 | DB). 6 | 7 | ## How to use 8 | 9 | 1. Install dependencies 10 | 11 | Use [poetry](https://python-poetry.org/) to install dependencies: 12 | 13 | ```bash 14 | poetry install 15 | ``` 16 | 17 | 2. Run migrations 18 | 19 | Run [alembic](https://alembic.sqlalchemy.org/en/latest/) to create the database 20 | and populate it with movie data: 21 | 22 | ```bash 23 | poetry run alembic upgrade head 24 | ``` 25 | 26 | 3. Run the server 27 | 28 | Run [uvicorn](https://www.uvicorn.org/) to run the server: 29 | 30 | ```bash 31 | poetry run uvicorn main:app --reload 32 | ``` 33 | 34 | The GraphQL API should now be available at http://localhost:8000/graphql 35 | 36 | ## Example query 37 | 38 | ```graphql 39 | query AllTopRatedMovies { 40 | topRatedMovies { 41 | id 42 | imageUrl 43 | imdbId 44 | imdbRating 45 | imdbRatingCount 46 | title 47 | year 48 | director { 49 | id 50 | name 51 | } 52 | } 53 | } 54 | ``` 55 | -------------------------------------------------------------------------------- /fastapi-sqlalchemy/alembic.ini: -------------------------------------------------------------------------------- 1 | # A generic, single database configuration. 2 | 3 | [alembic] 4 | # path to migration scripts 5 | script_location = alembic 6 | 7 | # template used to generate migration files 8 | # file_template = %%(rev)s_%%(slug)s 9 | 10 | # sys.path path, will be prepended to sys.path if present. 11 | # defaults to the current working directory. 12 | prepend_sys_path = . 13 | 14 | # timezone to use when rendering the date within the migration file 15 | # as well as the filename. 16 | # If specified, requires the python-dateutil library that can be 17 | # installed by adding `alembic[tz]` to the pip requirements 18 | # string value is passed to dateutil.tz.gettz() 19 | # leave blank for localtime 20 | # timezone = 21 | 22 | # max length of characters to apply to the 23 | # "slug" field 24 | # truncate_slug_length = 40 25 | 26 | # set to 'true' to run the environment during 27 | # the 'revision' command, regardless of autogenerate 28 | # revision_environment = false 29 | 30 | # set to 'true' to allow .pyc and .pyo files without 31 | # a source .py file to be detected as revisions in the 32 | # versions/ directory 33 | # sourceless = false 34 | 35 | # version location specification; This defaults 36 | # to alembic/versions. When using multiple version 37 | # directories, initial revisions must be specified with --version-path. 38 | # The path separator used here should be the separator specified by "version_path_separator" 39 | # version_locations = %(here)s/bar:%(here)s/bat:alembic/versions 40 | 41 | # Logging configuration 42 | [loggers] 43 | keys = root,sqlalchemy,alembic 44 | 45 | [handlers] 46 | keys = console 47 | 48 | [formatters] 49 | keys = generic 50 | 51 | [logger_root] 52 | level = WARN 53 | handlers = console 54 | qualname = 55 | 56 | [logger_sqlalchemy] 57 | level = WARN 58 | handlers = 59 | qualname = sqlalchemy.engine 60 | 61 | [logger_alembic] 62 | level = INFO 63 | handlers = 64 | qualname = alembic 65 | 66 | [handler_console] 67 | class = StreamHandler 68 | args = (sys.stderr,) 69 | level = NOTSET 70 | formatter = generic 71 | 72 | [formatter_generic] 73 | format = %(levelname)-5.5s [%(name)s] %(message)s 74 | datefmt = %H:%M:%S 75 | -------------------------------------------------------------------------------- /fastapi-sqlalchemy/alembic/README: -------------------------------------------------------------------------------- 1 | Generic single-database configuration. 2 | -------------------------------------------------------------------------------- /fastapi-sqlalchemy/alembic/env.py: -------------------------------------------------------------------------------- 1 | from logging.config import fileConfig 2 | 3 | from sqlalchemy import engine_from_config 4 | from sqlalchemy import pool 5 | 6 | from alembic import context 7 | 8 | # this is the Alembic Config object, which provides 9 | # access to the values within the .ini file in use. 10 | config = context.config # type: ignore 11 | 12 | # Interpret the config file for Python logging. 13 | # This line sets up loggers basically. 14 | fileConfig(config.config_file_name) 15 | 16 | # add your model's MetaData object here 17 | # for 'autogenerate' support 18 | # from myapp import mymodel 19 | # target_metadata = mymodel.Base.metadata 20 | # target_metadata = None 21 | 22 | from main.database import Base # noqa 23 | 24 | target_metadata = Base.metadata 25 | 26 | # other values from the config, defined by the needs of env.py, 27 | # can be acquired: 28 | # my_important_option = config.get_main_option("my_important_option") 29 | # ... etc. 30 | 31 | 32 | def get_url(): 33 | return "sqlite:///./db.sqlite3" 34 | 35 | 36 | def run_migrations_offline(): 37 | """Run migrations in 'offline' mode. 38 | 39 | This configures the context with just a URL 40 | and not an Engine, though an Engine is acceptable 41 | here as well. By skipping the Engine creation 42 | we don't even need a DBAPI to be available. 43 | 44 | Calls to context.execute() here emit the given string to the 45 | script output. 46 | 47 | """ 48 | url = get_url() 49 | context.configure( 50 | url=url, 51 | target_metadata=target_metadata, 52 | literal_binds=True, 53 | dialect_opts={"paramstyle": "named"}, 54 | ) 55 | 56 | with context.begin_transaction(): 57 | context.run_migrations() 58 | 59 | 60 | def run_migrations_online(): 61 | """Run migrations in 'online' mode. 62 | 63 | In this scenario we need to create an Engine 64 | and associate a connection with the context. 65 | 66 | """ 67 | configuration = config.get_section(config.config_ini_section) 68 | configuration["sqlalchemy.url"] = get_url() 69 | connectable = engine_from_config( 70 | configuration, 71 | prefix="sqlalchemy.", 72 | poolclass=pool.NullPool, 73 | ) 74 | 75 | with connectable.connect() as connection: 76 | context.configure(connection=connection, target_metadata=target_metadata) 77 | 78 | with context.begin_transaction(): 79 | context.run_migrations() 80 | 81 | 82 | if context.is_offline_mode(): 83 | run_migrations_offline() 84 | else: 85 | run_migrations_online() 86 | -------------------------------------------------------------------------------- /fastapi-sqlalchemy/alembic/script.py.mako: -------------------------------------------------------------------------------- 1 | """${message} 2 | 3 | Revision ID: ${up_revision} 4 | Revises: ${down_revision | comma,n} 5 | Create Date: ${create_date} 6 | 7 | """ 8 | from alembic import op 9 | import sqlalchemy as sa 10 | ${imports if imports else ""} 11 | 12 | # revision identifiers, used by Alembic. 13 | revision = ${repr(up_revision)} 14 | down_revision = ${repr(down_revision)} 15 | branch_labels = ${repr(branch_labels)} 16 | depends_on = ${repr(depends_on)} 17 | 18 | 19 | def upgrade(): 20 | ${upgrades if upgrades else "pass"} 21 | 22 | 23 | def downgrade(): 24 | ${downgrades if downgrades else "pass"} 25 | -------------------------------------------------------------------------------- /fastapi-sqlalchemy/alembic/versions/9bc8667ab6a6_add_initial_models.py: -------------------------------------------------------------------------------- 1 | """Add initial models 2 | 3 | Revision ID: 9bc8667ab6a6 4 | Revises: 5 | Create Date: 2021-09-10 16:00:02.842263 6 | 7 | """ 8 | 9 | from alembic import op 10 | import sqlalchemy as sa 11 | 12 | 13 | # revision identifiers, used by Alembic. 14 | revision = "9bc8667ab6a6" 15 | down_revision = None 16 | branch_labels = None 17 | depends_on = None 18 | 19 | 20 | def upgrade(): 21 | op.create_table( 22 | "directors", 23 | sa.Column("id", sa.Integer(), nullable=False), 24 | sa.Column("name", sa.String(), nullable=False), 25 | sa.PrimaryKeyConstraint("id"), 26 | ) 27 | op.create_index(op.f("ix_directors_id"), "directors", ["id"], unique=False) 28 | op.create_index(op.f("ix_directors_name"), "directors", ["name"], unique=True) 29 | op.create_table( 30 | "movies", 31 | sa.Column("id", sa.Integer(), nullable=False), 32 | sa.Column("title", sa.String(), nullable=False), 33 | sa.Column("imdb_id", sa.String(), nullable=False), 34 | sa.Column("year", sa.Integer(), nullable=False), 35 | sa.Column("image_url", sa.String(), nullable=False), 36 | sa.Column("imdb_rating", sa.Float(), nullable=False), 37 | sa.Column("imdb_rating_count", sa.String(), nullable=False), 38 | sa.Column("director_id", sa.Integer(), nullable=False), 39 | sa.ForeignKeyConstraint( 40 | ["director_id"], 41 | ["directors.id"], 42 | ), 43 | sa.PrimaryKeyConstraint("id"), 44 | sa.UniqueConstraint("title"), 45 | ) 46 | op.create_index(op.f("ix_movies_id"), "movies", ["id"], unique=False) 47 | op.create_index(op.f("ix_movies_imdb_id"), "movies", ["imdb_id"], unique=True) 48 | 49 | 50 | def downgrade(): 51 | op.drop_index(op.f("ix_movies_imdb_id"), table_name="movies") 52 | op.drop_index(op.f("ix_movies_id"), table_name="movies") 53 | op.drop_table("movies") 54 | op.drop_index(op.f("ix_directors_name"), table_name="directors") 55 | op.drop_index(op.f("ix_directors_id"), table_name="directors") 56 | op.drop_table("directors") 57 | -------------------------------------------------------------------------------- /fastapi-sqlalchemy/alembic/versions/bea5e58f3328_add_data.py: -------------------------------------------------------------------------------- 1 | """Add data 2 | 3 | Revision ID: bea5e58f3328 4 | Revises: 9bc8667ab6a6 5 | Create Date: 2021-09-10 16:00:20.280277 6 | 7 | """ 8 | 9 | import json 10 | from pathlib import Path 11 | 12 | from alembic import op 13 | from sqlalchemy import orm, select 14 | from sqlalchemy.exc import NoResultFound 15 | 16 | from main.models import Director, Movie 17 | 18 | 19 | # revision identifiers, used by Alembic. 20 | revision = "bea5e58f3328" 21 | down_revision = "9bc8667ab6a6" 22 | branch_labels = None 23 | depends_on = None 24 | 25 | 26 | current_dir = Path(__file__).parent.resolve() 27 | data_file = current_dir.parent.parent.parent / "common-data" / "movies.json" 28 | 29 | 30 | def upgrade(): 31 | bind = op.get_bind() 32 | session = orm.Session(bind=bind) 33 | 34 | with data_file.open() as f: 35 | json_data = json.load(f) 36 | 37 | for movie_data in json_data: 38 | try: 39 | director = session.execute( 40 | select(Director).filter_by(name=movie_data["director"]["name"]) 41 | ).scalar_one() 42 | except NoResultFound: 43 | director = Director(name=movie_data["director"]["name"]) 44 | session.add(director) 45 | session.commit() 46 | 47 | movie = Movie( 48 | imdb_id=movie_data["imdb_id"], 49 | title=movie_data["title"], 50 | year=movie_data["year"], 51 | image_url=movie_data["image_url"], 52 | imdb_rating=movie_data["imdb_rating"], 53 | imdb_rating_count=movie_data["imdb_rating_count"], 54 | director=director, 55 | ) 56 | session.add(movie) 57 | session.commit() 58 | 59 | 60 | def downgrade(): 61 | bind = op.get_bind() 62 | session = orm.Session(bind=bind) 63 | 64 | session.execute("DELETE FROM movies") 65 | session.execute("DELETE FROM directors") 66 | session.commit() 67 | session.close() 68 | -------------------------------------------------------------------------------- /fastapi-sqlalchemy/api/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/strawberry-graphql/examples/8a1cddbc41d3e7dfdcf2a6e1192b2bb730e3b7a1/fastapi-sqlalchemy/api/__init__.py -------------------------------------------------------------------------------- /fastapi-sqlalchemy/api/definitions/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/strawberry-graphql/examples/8a1cddbc41d3e7dfdcf2a6e1192b2bb730e3b7a1/fastapi-sqlalchemy/api/definitions/__init__.py -------------------------------------------------------------------------------- /fastapi-sqlalchemy/api/definitions/director.py: -------------------------------------------------------------------------------- 1 | import strawberry 2 | 3 | from main.models import Director as DirectorModel 4 | 5 | 6 | @strawberry.type 7 | class Director: 8 | id: int 9 | name: str 10 | 11 | @classmethod 12 | def from_instance(cls, instance: DirectorModel): 13 | return cls( 14 | id=instance.id, 15 | name=instance.name, 16 | ) 17 | -------------------------------------------------------------------------------- /fastapi-sqlalchemy/api/definitions/movie.py: -------------------------------------------------------------------------------- 1 | import strawberry 2 | 3 | from main.models import Movie as MovieModel 4 | 5 | from .director import Director 6 | 7 | 8 | @strawberry.type 9 | class Movie: 10 | id: int 11 | imdb_id: str 12 | title: str 13 | year: int 14 | image_url: str 15 | imdb_rating: float 16 | imdb_rating_count: str 17 | 18 | instance: strawberry.Private[MovieModel] 19 | 20 | @strawberry.field 21 | def director(self) -> Director: 22 | return Director.from_instance(self.instance.director) 23 | 24 | @classmethod 25 | def from_instance(cls, instance: MovieModel): 26 | return cls( 27 | instance=instance, 28 | id=instance.id, 29 | imdb_id=instance.imdb_id, 30 | title=instance.title, 31 | year=instance.year, 32 | image_url=instance.image_url, 33 | imdb_rating=instance.imdb_rating, 34 | imdb_rating_count=instance.imdb_rating_count, 35 | ) 36 | -------------------------------------------------------------------------------- /fastapi-sqlalchemy/api/schema.py: -------------------------------------------------------------------------------- 1 | from typing import List 2 | 3 | import strawberry 4 | from strawberry.extensions import Extension 5 | 6 | from main.models import get_movies 7 | from main.database import SessionLocal 8 | 9 | from .definitions.movie import Movie 10 | 11 | 12 | class SQLAlchemySession(Extension): 13 | def on_request_start(self): 14 | self.execution_context.context["db"] = SessionLocal() 15 | 16 | def on_request_end(self): 17 | self.execution_context.context["db"].close() 18 | 19 | 20 | @strawberry.type 21 | class Query: 22 | @strawberry.field 23 | def top_rated_movies(self, info, limit: int = 250) -> List[Movie]: 24 | db = info.context["db"] 25 | movies = get_movies(db, limit=limit) 26 | return [Movie.from_instance(movie) for movie in movies] 27 | 28 | 29 | schema = strawberry.Schema(Query, extensions=[SQLAlchemySession]) 30 | -------------------------------------------------------------------------------- /fastapi-sqlalchemy/main/__init__.py: -------------------------------------------------------------------------------- 1 | from fastapi import FastAPI 2 | from strawberry.asgi import GraphQL 3 | 4 | from api.schema import schema 5 | 6 | graphql_app = GraphQL(schema) 7 | 8 | app = FastAPI() 9 | app.mount("/graphql", graphql_app) 10 | -------------------------------------------------------------------------------- /fastapi-sqlalchemy/main/database.py: -------------------------------------------------------------------------------- 1 | from sqlalchemy import create_engine 2 | from sqlalchemy.ext.declarative import declarative_base 3 | from sqlalchemy.orm import sessionmaker 4 | 5 | 6 | SQLALCHEMY_DATABASE_URL = "sqlite:///./db.sqlite3" 7 | 8 | engine = create_engine( 9 | SQLALCHEMY_DATABASE_URL, connect_args={"check_same_thread": False}, future=True 10 | ) 11 | SessionLocal = sessionmaker(autocommit=False, autoflush=False, bind=engine, future=True) 12 | 13 | Base = declarative_base() 14 | -------------------------------------------------------------------------------- /fastapi-sqlalchemy/main/models.py: -------------------------------------------------------------------------------- 1 | from sqlalchemy import Column, Integer, String, Float, ForeignKey, select 2 | from sqlalchemy.orm import relationship, joinedload 3 | from sqlalchemy.orm import Session 4 | 5 | from .database import Base 6 | 7 | 8 | class Director(Base): 9 | __tablename__ = "directors" 10 | 11 | id: int = Column(Integer, primary_key=True, index=True, nullable=False) 12 | name: str = Column(String, unique=True, index=True, nullable=False) 13 | 14 | 15 | class Movie(Base): 16 | __tablename__ = "movies" 17 | 18 | id: int = Column(Integer, primary_key=True, index=True, nullable=False) 19 | title: str = Column(String, unique=True, nullable=False) 20 | imdb_id: str = Column(String, unique=True, index=True, nullable=False) 21 | year: int = Column(Integer, nullable=False) 22 | image_url: str = Column(String, nullable=False) 23 | imdb_rating: float = Column(Float, nullable=False) 24 | imdb_rating_count: str = Column(String, nullable=False) 25 | 26 | director_id: int = Column(Integer, ForeignKey("directors.id"), nullable=False) 27 | director: Director = relationship("Director") 28 | 29 | 30 | def get_movies(db: Session, limit: int = 250): 31 | query = ( 32 | select(Movie) 33 | .options(joinedload(Movie.director)) 34 | .order_by(Movie.imdb_rating.desc()) 35 | .limit(limit) 36 | ) 37 | 38 | result = db.execute(query).unique() 39 | return result.scalars() 40 | -------------------------------------------------------------------------------- /fastapi-sqlalchemy/poetry.lock: -------------------------------------------------------------------------------- 1 | [[package]] 2 | name = "alembic" 3 | version = "1.7.1" 4 | description = "A database migration tool for SQLAlchemy." 5 | category = "main" 6 | optional = false 7 | python-versions = ">=3.6" 8 | 9 | [package.dependencies] 10 | importlib-metadata = {version = "*", markers = "python_version < \"3.8\""} 11 | importlib-resources = {version = "*", markers = "python_version < \"3.9\""} 12 | Mako = "*" 13 | SQLAlchemy = ">=1.3.0" 14 | 15 | [package.extras] 16 | tz = ["python-dateutil"] 17 | 18 | [[package]] 19 | name = "asgiref" 20 | version = "3.4.1" 21 | description = "ASGI specs, helper code, and adapters" 22 | category = "main" 23 | optional = false 24 | python-versions = ">=3.6" 25 | 26 | [package.dependencies] 27 | typing-extensions = {version = "*", markers = "python_version < \"3.8\""} 28 | 29 | [package.extras] 30 | tests = ["pytest", "pytest-asyncio", "mypy (>=0.800)"] 31 | 32 | [[package]] 33 | name = "attrs" 34 | version = "21.2.0" 35 | description = "Classes Without Boilerplate" 36 | category = "dev" 37 | optional = false 38 | python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*, !=3.4.*" 39 | 40 | [package.extras] 41 | dev = ["coverage[toml] (>=5.0.2)", "hypothesis", "pympler", "pytest (>=4.3.0)", "six", "mypy", "pytest-mypy-plugins", "zope.interface", "furo", "sphinx", "sphinx-notfound-page", "pre-commit"] 42 | docs = ["furo", "sphinx", "zope.interface", "sphinx-notfound-page"] 43 | tests = ["coverage[toml] (>=5.0.2)", "hypothesis", "pympler", "pytest (>=4.3.0)", "six", "mypy", "pytest-mypy-plugins", "zope.interface"] 44 | tests_no_zope = ["coverage[toml] (>=5.0.2)", "hypothesis", "pympler", "pytest (>=4.3.0)", "six", "mypy", "pytest-mypy-plugins"] 45 | 46 | [[package]] 47 | name = "black" 48 | version = "21.8b0" 49 | description = "The uncompromising code formatter." 50 | category = "dev" 51 | optional = false 52 | python-versions = ">=3.6.2" 53 | 54 | [package.dependencies] 55 | click = ">=7.1.2" 56 | mypy-extensions = ">=0.4.3" 57 | pathspec = ">=0.9.0,<1" 58 | platformdirs = ">=2" 59 | regex = ">=2020.1.8" 60 | tomli = ">=0.2.6,<2.0.0" 61 | typed-ast = {version = ">=1.4.2", markers = "python_version < \"3.8\""} 62 | typing-extensions = [ 63 | {version = ">=3.10.0.0", markers = "python_version < \"3.10\""}, 64 | {version = "!=3.10.0.1", markers = "python_version >= \"3.10\""}, 65 | ] 66 | 67 | [package.extras] 68 | colorama = ["colorama (>=0.4.3)"] 69 | d = ["aiohttp (>=3.6.0)", "aiohttp-cors (>=0.4.0)"] 70 | jupyter = ["ipython (>=7.8.0)", "tokenize-rt (>=3.2.0)"] 71 | python2 = ["typed-ast (>=1.4.2)"] 72 | uvloop = ["uvloop (>=0.15.2)"] 73 | 74 | [[package]] 75 | name = "cached-property" 76 | version = "1.5.2" 77 | description = "A decorator for caching properties in classes." 78 | category = "main" 79 | optional = false 80 | python-versions = "*" 81 | 82 | [[package]] 83 | name = "click" 84 | version = "8.0.1" 85 | description = "Composable command line interface toolkit" 86 | category = "main" 87 | optional = false 88 | python-versions = ">=3.6" 89 | 90 | [package.dependencies] 91 | colorama = {version = "*", markers = "platform_system == \"Windows\""} 92 | importlib-metadata = {version = "*", markers = "python_version < \"3.8\""} 93 | 94 | [[package]] 95 | name = "colorama" 96 | version = "0.4.4" 97 | description = "Cross-platform colored terminal text." 98 | category = "main" 99 | optional = false 100 | python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*, !=3.4.*" 101 | 102 | [[package]] 103 | name = "fastapi" 104 | version = "0.68.1" 105 | description = "FastAPI framework, high performance, easy to learn, fast to code, ready for production" 106 | category = "main" 107 | optional = false 108 | python-versions = ">=3.6" 109 | 110 | [package.dependencies] 111 | pydantic = ">=1.6.2,<1.7 || >1.7,<1.7.1 || >1.7.1,<1.7.2 || >1.7.2,<1.7.3 || >1.7.3,<1.8 || >1.8,<1.8.1 || >1.8.1,<2.0.0" 112 | starlette = "0.14.2" 113 | 114 | [package.extras] 115 | all = ["requests (>=2.24.0,<3.0.0)", "aiofiles (>=0.5.0,<0.6.0)", "jinja2 (>=2.11.2,<3.0.0)", "python-multipart (>=0.0.5,<0.0.6)", "itsdangerous (>=1.1.0,<2.0.0)", "pyyaml (>=5.3.1,<6.0.0)", "graphene (>=2.1.8,<3.0.0)", "ujson (>=4.0.1,<5.0.0)", "orjson (>=3.2.1,<4.0.0)", "email_validator (>=1.1.1,<2.0.0)", "uvicorn[standard] (>=0.12.0,<0.14.0)", "async_exit_stack (>=1.0.1,<2.0.0)", "async_generator (>=1.10,<2.0.0)"] 116 | dev = ["python-jose[cryptography] (>=3.3.0,<4.0.0)", "passlib[bcrypt] (>=1.7.2,<2.0.0)", "autoflake (>=1.3.1,<2.0.0)", "flake8 (>=3.8.3,<4.0.0)", "uvicorn[standard] (>=0.12.0,<0.14.0)", "graphene (>=2.1.8,<3.0.0)"] 117 | doc = ["mkdocs (>=1.1.2,<2.0.0)", "mkdocs-material (>=7.1.9,<8.0.0)", "mdx-include (>=1.4.1,<2.0.0)", "mkdocs-markdownextradata-plugin (>=0.1.7,<0.2.0)", "typer-cli (>=0.0.12,<0.0.13)", "pyyaml (>=5.3.1,<6.0.0)"] 118 | test = ["pytest (>=6.2.4,<7.0.0)", "pytest-cov (>=2.12.0,<3.0.0)", "pytest-asyncio (>=0.14.0,<0.15.0)", "mypy (==0.812)", "flake8 (>=3.8.3,<4.0.0)", "black (==20.8b1)", "isort (>=5.0.6,<6.0.0)", "requests (>=2.24.0,<3.0.0)", "httpx (>=0.14.0,<0.15.0)", "email_validator (>=1.1.1,<2.0.0)", "sqlalchemy (>=1.3.18,<1.4.0)", "peewee (>=3.13.3,<4.0.0)", "databases[sqlite] (>=0.3.2,<0.4.0)", "orjson (>=3.2.1,<4.0.0)", "ujson (>=4.0.1,<5.0.0)", "async_exit_stack (>=1.0.1,<2.0.0)", "async_generator (>=1.10,<2.0.0)", "python-multipart (>=0.0.5,<0.0.6)", "aiofiles (>=0.5.0,<0.6.0)", "flask (>=1.1.2,<2.0.0)"] 119 | 120 | [[package]] 121 | name = "flake8" 122 | version = "3.9.2" 123 | description = "the modular source code checker: pep8 pyflakes and co" 124 | category = "dev" 125 | optional = false 126 | python-versions = "!=3.0.*,!=3.1.*,!=3.2.*,!=3.3.*,!=3.4.*,>=2.7" 127 | 128 | [package.dependencies] 129 | importlib-metadata = {version = "*", markers = "python_version < \"3.8\""} 130 | mccabe = ">=0.6.0,<0.7.0" 131 | pycodestyle = ">=2.7.0,<2.8.0" 132 | pyflakes = ">=2.3.0,<2.4.0" 133 | 134 | [[package]] 135 | name = "flake8-black" 136 | version = "0.2.3" 137 | description = "flake8 plugin to call black as a code style validator" 138 | category = "dev" 139 | optional = false 140 | python-versions = "*" 141 | 142 | [package.dependencies] 143 | black = "*" 144 | flake8 = ">=3.0.0" 145 | toml = "*" 146 | 147 | [[package]] 148 | name = "flake8-bugbear" 149 | version = "21.4.3" 150 | description = "A plugin for flake8 finding likely bugs and design problems in your program. Contains warnings that don't belong in pyflakes and pycodestyle." 151 | category = "dev" 152 | optional = false 153 | python-versions = ">=3.6" 154 | 155 | [package.dependencies] 156 | attrs = ">=19.2.0" 157 | flake8 = ">=3.0.0" 158 | 159 | [package.extras] 160 | dev = ["coverage", "black", "hypothesis", "hypothesmith"] 161 | 162 | [[package]] 163 | name = "graphql-core" 164 | version = "3.1.6" 165 | description = "GraphQL implementation for Python, a port of GraphQL.js, the JavaScript reference implementation for GraphQL." 166 | category = "main" 167 | optional = false 168 | python-versions = ">=3.6,<4" 169 | 170 | [[package]] 171 | name = "greenlet" 172 | version = "1.1.1" 173 | description = "Lightweight in-process concurrent programming" 174 | category = "main" 175 | optional = false 176 | python-versions = ">=2.7,!=3.0.*,!=3.1.*,!=3.2.*,!=3.3.*,!=3.4.*" 177 | 178 | [package.extras] 179 | docs = ["sphinx"] 180 | 181 | [[package]] 182 | name = "h11" 183 | version = "0.12.0" 184 | description = "A pure-Python, bring-your-own-I/O implementation of HTTP/1.1" 185 | category = "main" 186 | optional = false 187 | python-versions = ">=3.6" 188 | 189 | [[package]] 190 | name = "httptools" 191 | version = "0.2.0" 192 | description = "A collection of framework independent HTTP protocol utils." 193 | category = "main" 194 | optional = false 195 | python-versions = "*" 196 | 197 | [package.extras] 198 | test = ["Cython (==0.29.22)"] 199 | 200 | [[package]] 201 | name = "importlib-metadata" 202 | version = "4.8.1" 203 | description = "Read metadata from Python packages" 204 | category = "main" 205 | optional = false 206 | python-versions = ">=3.6" 207 | 208 | [package.dependencies] 209 | typing-extensions = {version = ">=3.6.4", markers = "python_version < \"3.8\""} 210 | zipp = ">=0.5" 211 | 212 | [package.extras] 213 | docs = ["sphinx", "jaraco.packaging (>=8.2)", "rst.linker (>=1.9)"] 214 | perf = ["ipython"] 215 | testing = ["pytest (>=4.6)", "pytest-checkdocs (>=2.4)", "pytest-flake8", "pytest-cov", "pytest-enabler (>=1.0.1)", "packaging", "pep517", "pyfakefs", "flufl.flake8", "pytest-perf (>=0.9.2)", "pytest-black (>=0.3.7)", "pytest-mypy", "importlib-resources (>=1.3)"] 216 | 217 | [[package]] 218 | name = "importlib-resources" 219 | version = "5.2.2" 220 | description = "Read resources from Python packages" 221 | category = "main" 222 | optional = false 223 | python-versions = ">=3.6" 224 | 225 | [package.dependencies] 226 | zipp = {version = ">=3.1.0", markers = "python_version < \"3.10\""} 227 | 228 | [package.extras] 229 | docs = ["sphinx", "jaraco.packaging (>=8.2)", "rst.linker (>=1.9)"] 230 | testing = ["pytest (>=4.6)", "pytest-checkdocs (>=2.4)", "pytest-flake8", "pytest-cov", "pytest-enabler (>=1.0.1)", "pytest-black (>=0.3.7)", "pytest-mypy"] 231 | 232 | [[package]] 233 | name = "mako" 234 | version = "1.1.5" 235 | description = "A super-fast templating language that borrows the best ideas from the existing templating languages." 236 | category = "main" 237 | optional = false 238 | python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*" 239 | 240 | [package.dependencies] 241 | MarkupSafe = ">=0.9.2" 242 | 243 | [package.extras] 244 | babel = ["babel"] 245 | lingua = ["lingua"] 246 | 247 | [[package]] 248 | name = "markupsafe" 249 | version = "2.0.1" 250 | description = "Safely add untrusted strings to HTML/XML markup." 251 | category = "main" 252 | optional = false 253 | python-versions = ">=3.6" 254 | 255 | [[package]] 256 | name = "mccabe" 257 | version = "0.6.1" 258 | description = "McCabe checker, plugin for flake8" 259 | category = "dev" 260 | optional = false 261 | python-versions = "*" 262 | 263 | [[package]] 264 | name = "mypy" 265 | version = "0.910" 266 | description = "Optional static typing for Python" 267 | category = "main" 268 | optional = false 269 | python-versions = ">=3.5" 270 | 271 | [package.dependencies] 272 | mypy-extensions = ">=0.4.3,<0.5.0" 273 | toml = "*" 274 | typed-ast = {version = ">=1.4.0,<1.5.0", markers = "python_version < \"3.8\""} 275 | typing-extensions = ">=3.7.4" 276 | 277 | [package.extras] 278 | dmypy = ["psutil (>=4.0)"] 279 | python2 = ["typed-ast (>=1.4.0,<1.5.0)"] 280 | 281 | [[package]] 282 | name = "mypy-extensions" 283 | version = "0.4.3" 284 | description = "Experimental type system extensions for programs checked with the mypy typechecker." 285 | category = "main" 286 | optional = false 287 | python-versions = "*" 288 | 289 | [[package]] 290 | name = "pathspec" 291 | version = "0.9.0" 292 | description = "Utility library for gitignore style pattern matching of file paths." 293 | category = "dev" 294 | optional = false 295 | python-versions = "!=3.0.*,!=3.1.*,!=3.2.*,!=3.3.*,!=3.4.*,>=2.7" 296 | 297 | [[package]] 298 | name = "platformdirs" 299 | version = "2.3.0" 300 | description = "A small Python module for determining appropriate platform-specific dirs, e.g. a \"user data dir\"." 301 | category = "dev" 302 | optional = false 303 | python-versions = ">=3.6" 304 | 305 | [package.extras] 306 | docs = ["Sphinx (>=4)", "furo (>=2021.7.5b38)", "proselint (>=0.10.2)", "sphinx-autodoc-typehints (>=1.12)"] 307 | test = ["appdirs (==1.4.4)", "pytest (>=6)", "pytest-cov (>=2.7)", "pytest-mock (>=3.6)"] 308 | 309 | [[package]] 310 | name = "pycodestyle" 311 | version = "2.7.0" 312 | description = "Python style guide checker" 313 | category = "dev" 314 | optional = false 315 | python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*" 316 | 317 | [[package]] 318 | name = "pydantic" 319 | version = "1.8.2" 320 | description = "Data validation and settings management using python 3.6 type hinting" 321 | category = "main" 322 | optional = false 323 | python-versions = ">=3.6.1" 324 | 325 | [package.dependencies] 326 | typing-extensions = ">=3.7.4.3" 327 | 328 | [package.extras] 329 | dotenv = ["python-dotenv (>=0.10.4)"] 330 | email = ["email-validator (>=1.0.3)"] 331 | 332 | [[package]] 333 | name = "pyflakes" 334 | version = "2.3.1" 335 | description = "passive checker of Python programs" 336 | category = "dev" 337 | optional = false 338 | python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*" 339 | 340 | [[package]] 341 | name = "pygments" 342 | version = "2.10.0" 343 | description = "Pygments is a syntax highlighting package written in Python." 344 | category = "main" 345 | optional = false 346 | python-versions = ">=3.5" 347 | 348 | [[package]] 349 | name = "python-dateutil" 350 | version = "2.8.2" 351 | description = "Extensions to the standard Python datetime module" 352 | category = "main" 353 | optional = false 354 | python-versions = "!=3.0.*,!=3.1.*,!=3.2.*,>=2.7" 355 | 356 | [package.dependencies] 357 | six = ">=1.5" 358 | 359 | [[package]] 360 | name = "python-dotenv" 361 | version = "0.19.0" 362 | description = "Read key-value pairs from a .env file and set them as environment variables" 363 | category = "main" 364 | optional = false 365 | python-versions = ">=3.5" 366 | 367 | [package.extras] 368 | cli = ["click (>=5.0)"] 369 | 370 | [[package]] 371 | name = "python-multipart" 372 | version = "0.0.5" 373 | description = "A streaming multipart parser for Python" 374 | category = "main" 375 | optional = false 376 | python-versions = "*" 377 | 378 | [package.dependencies] 379 | six = ">=1.4.0" 380 | 381 | [[package]] 382 | name = "pyyaml" 383 | version = "5.4.1" 384 | description = "YAML parser and emitter for Python" 385 | category = "main" 386 | optional = false 387 | python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*, !=3.4.*, !=3.5.*" 388 | 389 | [[package]] 390 | name = "regex" 391 | version = "2021.8.28" 392 | description = "Alternative regular expression module, to replace re." 393 | category = "dev" 394 | optional = false 395 | python-versions = "*" 396 | 397 | [[package]] 398 | name = "six" 399 | version = "1.16.0" 400 | description = "Python 2 and 3 compatibility utilities" 401 | category = "main" 402 | optional = false 403 | python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*" 404 | 405 | [[package]] 406 | name = "sqlalchemy" 407 | version = "1.4.23" 408 | description = "Database Abstraction Library" 409 | category = "main" 410 | optional = false 411 | python-versions = "!=3.0.*,!=3.1.*,!=3.2.*,!=3.3.*,!=3.4.*,!=3.5.*,>=2.7" 412 | 413 | [package.dependencies] 414 | greenlet = {version = "!=0.4.17", markers = "python_version >= \"3\" and platform_machine in \"x86_64 X86_64 aarch64 AARCH64 ppc64le PPC64LE amd64 AMD64 win32 WIN32\""} 415 | importlib-metadata = {version = "*", markers = "python_version < \"3.8\""} 416 | mypy = {version = ">=0.910", optional = true, markers = "python_version >= \"3\" and extra == \"mypy\""} 417 | sqlalchemy2-stubs = {version = "*", optional = true, markers = "extra == \"mypy\""} 418 | 419 | [package.extras] 420 | aiomysql = ["greenlet (!=0.4.17)", "aiomysql"] 421 | aiosqlite = ["greenlet (!=0.4.17)", "aiosqlite"] 422 | asyncio = ["greenlet (!=0.4.17)"] 423 | mariadb_connector = ["mariadb (>=1.0.1)"] 424 | mssql = ["pyodbc"] 425 | mssql_pymssql = ["pymssql"] 426 | mssql_pyodbc = ["pyodbc"] 427 | mypy = ["sqlalchemy2-stubs", "mypy (>=0.910)"] 428 | mysql = ["mysqlclient (>=1.4.0,<2)", "mysqlclient (>=1.4.0)"] 429 | mysql_connector = ["mysqlconnector"] 430 | oracle = ["cx_oracle (>=7,<8)", "cx_oracle (>=7)"] 431 | postgresql = ["psycopg2 (>=2.7)"] 432 | postgresql_asyncpg = ["greenlet (!=0.4.17)", "asyncpg"] 433 | postgresql_pg8000 = ["pg8000 (>=1.16.6)"] 434 | postgresql_psycopg2binary = ["psycopg2-binary"] 435 | postgresql_psycopg2cffi = ["psycopg2cffi"] 436 | pymysql = ["pymysql (<1)", "pymysql"] 437 | sqlcipher = ["sqlcipher3-binary"] 438 | 439 | [[package]] 440 | name = "sqlalchemy2-stubs" 441 | version = "0.0.2a15" 442 | description = "Typing Stubs for SQLAlchemy 1.4" 443 | category = "main" 444 | optional = false 445 | python-versions = ">=3.6" 446 | 447 | [package.dependencies] 448 | typing-extensions = ">=3.7.4" 449 | 450 | [[package]] 451 | name = "starlette" 452 | version = "0.14.2" 453 | description = "The little ASGI library that shines." 454 | category = "main" 455 | optional = false 456 | python-versions = ">=3.6" 457 | 458 | [package.extras] 459 | full = ["aiofiles", "graphene", "itsdangerous", "jinja2", "python-multipart", "pyyaml", "requests"] 460 | 461 | [[package]] 462 | name = "strawberry-graphql" 463 | version = "0.77.10" 464 | description = "A library for creating GraphQL APIs" 465 | category = "main" 466 | optional = false 467 | python-versions = ">=3.7,<4.0" 468 | 469 | [package.dependencies] 470 | cached-property = ">=1.5.2,<2.0.0" 471 | click = ">=7.0,<9.0" 472 | graphql-core = ">=3.1.0,<3.2.0" 473 | pygments = ">=2.3,<3.0" 474 | python-dateutil = ">=2.7.0,<3.0.0" 475 | python-multipart = ">=0.0.5,<0.0.6" 476 | starlette = {version = ">=0.13.6,<0.17.0", optional = true, markers = "extra == \"asgi\" or extra == \"debug-server\""} 477 | typing_extensions = ">=3.7.4,<4.0.0" 478 | 479 | [package.extras] 480 | asgi = ["starlette (>=0.13.6,<0.17.0)"] 481 | debug-server = ["starlette (>=0.13.6,<0.17.0)", "uvicorn (>=0.11.6,<0.16.0)"] 482 | django = ["django (>=2,<4)", "asgiref (>=3.2,<4.0)"] 483 | flask = ["flask (>=1.1,<2.0)"] 484 | opentelemetry = ["opentelemetry-api (<2)", "opentelemetry-sdk (<2)"] 485 | pydantic = ["pydantic (<2)"] 486 | sanic = ["sanic (>=20.12.2,<21.0.0)"] 487 | aiohttp = ["aiohttp (>=3.7.4.post0,<4.0.0)"] 488 | 489 | [[package]] 490 | name = "toml" 491 | version = "0.10.2" 492 | description = "Python Library for Tom's Obvious, Minimal Language" 493 | category = "main" 494 | optional = false 495 | python-versions = ">=2.6, !=3.0.*, !=3.1.*, !=3.2.*" 496 | 497 | [[package]] 498 | name = "tomli" 499 | version = "1.2.1" 500 | description = "A lil' TOML parser" 501 | category = "dev" 502 | optional = false 503 | python-versions = ">=3.6" 504 | 505 | [[package]] 506 | name = "typed-ast" 507 | version = "1.4.3" 508 | description = "a fork of Python 2 and 3 ast modules with type comment support" 509 | category = "main" 510 | optional = false 511 | python-versions = "*" 512 | 513 | [[package]] 514 | name = "typing-extensions" 515 | version = "3.10.0.2" 516 | description = "Backported and Experimental Type Hints for Python 3.5+" 517 | category = "main" 518 | optional = false 519 | python-versions = "*" 520 | 521 | [[package]] 522 | name = "uvicorn" 523 | version = "0.15.0" 524 | description = "The lightning-fast ASGI server." 525 | category = "main" 526 | optional = false 527 | python-versions = "*" 528 | 529 | [package.dependencies] 530 | asgiref = ">=3.4.0" 531 | click = ">=7.0" 532 | colorama = {version = ">=0.4", optional = true, markers = "sys_platform == \"win32\" and extra == \"standard\""} 533 | h11 = ">=0.8" 534 | httptools = {version = ">=0.2.0,<0.3.0", optional = true, markers = "extra == \"standard\""} 535 | python-dotenv = {version = ">=0.13", optional = true, markers = "extra == \"standard\""} 536 | PyYAML = {version = ">=5.1", optional = true, markers = "extra == \"standard\""} 537 | typing-extensions = {version = "*", markers = "python_version < \"3.8\""} 538 | uvloop = {version = ">=0.14.0,<0.15.0 || >0.15.0,<0.15.1 || >0.15.1", optional = true, markers = "sys_platform != \"win32\" and sys_platform != \"cygwin\" and platform_python_implementation != \"PyPy\" and extra == \"standard\""} 539 | watchgod = {version = ">=0.6", optional = true, markers = "extra == \"standard\""} 540 | websockets = {version = ">=9.1", optional = true, markers = "extra == \"standard\""} 541 | 542 | [package.extras] 543 | standard = ["websockets (>=9.1)", "httptools (>=0.2.0,<0.3.0)", "watchgod (>=0.6)", "python-dotenv (>=0.13)", "PyYAML (>=5.1)", "uvloop (>=0.14.0,!=0.15.0,!=0.15.1)", "colorama (>=0.4)"] 544 | 545 | [[package]] 546 | name = "uvloop" 547 | version = "0.16.0" 548 | description = "Fast implementation of asyncio event loop on top of libuv" 549 | category = "main" 550 | optional = false 551 | python-versions = ">=3.7" 552 | 553 | [package.extras] 554 | dev = ["Cython (>=0.29.24,<0.30.0)", "pytest (>=3.6.0)", "Sphinx (>=4.1.2,<4.2.0)", "sphinxcontrib-asyncio (>=0.3.0,<0.4.0)", "sphinx-rtd-theme (>=0.5.2,<0.6.0)", "aiohttp", "flake8 (>=3.9.2,<3.10.0)", "psutil", "pycodestyle (>=2.7.0,<2.8.0)", "pyOpenSSL (>=19.0.0,<19.1.0)", "mypy (>=0.800)"] 555 | docs = ["Sphinx (>=4.1.2,<4.2.0)", "sphinxcontrib-asyncio (>=0.3.0,<0.4.0)", "sphinx-rtd-theme (>=0.5.2,<0.6.0)"] 556 | test = ["aiohttp", "flake8 (>=3.9.2,<3.10.0)", "psutil", "pycodestyle (>=2.7.0,<2.8.0)", "pyOpenSSL (>=19.0.0,<19.1.0)", "mypy (>=0.800)"] 557 | 558 | [[package]] 559 | name = "watchgod" 560 | version = "0.7" 561 | description = "Simple, modern file watching and code reload in python." 562 | category = "main" 563 | optional = false 564 | python-versions = ">=3.5" 565 | 566 | [[package]] 567 | name = "websockets" 568 | version = "10.0" 569 | description = "An implementation of the WebSocket Protocol (RFC 6455 & 7692)" 570 | category = "main" 571 | optional = false 572 | python-versions = ">=3.7" 573 | 574 | [[package]] 575 | name = "zipp" 576 | version = "3.5.0" 577 | description = "Backport of pathlib-compatible object wrapper for zip files" 578 | category = "main" 579 | optional = false 580 | python-versions = ">=3.6" 581 | 582 | [package.extras] 583 | docs = ["sphinx", "jaraco.packaging (>=8.2)", "rst.linker (>=1.9)"] 584 | testing = ["pytest (>=4.6)", "pytest-checkdocs (>=2.4)", "pytest-flake8", "pytest-cov", "pytest-enabler (>=1.0.1)", "jaraco.itertools", "func-timeout", "pytest-black (>=0.3.7)", "pytest-mypy"] 585 | 586 | [metadata] 587 | lock-version = "1.1" 588 | python-versions = "^3.7" 589 | content-hash = "98fa69364a20e1543505c385c05fd9be26fdc5abbb60fc0e52136a65a1036d88" 590 | 591 | [metadata.files] 592 | alembic = [ 593 | {file = "alembic-1.7.1-py3-none-any.whl", hash = "sha256:25f996b7408b11493d6a2d669fd9d2ff8d87883fe7434182bc7669d6caa526ab"}, 594 | {file = "alembic-1.7.1.tar.gz", hash = "sha256:aea964d3dcc9c205b8759e4e9c1c3935ea3afeee259bffd7ed8414f8085140fb"}, 595 | ] 596 | asgiref = [ 597 | {file = "asgiref-3.4.1-py3-none-any.whl", hash = "sha256:ffc141aa908e6f175673e7b1b3b7af4fdb0ecb738fc5c8b88f69f055c2415214"}, 598 | {file = "asgiref-3.4.1.tar.gz", hash = "sha256:4ef1ab46b484e3c706329cedeff284a5d40824200638503f5768edb6de7d58e9"}, 599 | ] 600 | attrs = [ 601 | {file = "attrs-21.2.0-py2.py3-none-any.whl", hash = "sha256:149e90d6d8ac20db7a955ad60cf0e6881a3f20d37096140088356da6c716b0b1"}, 602 | {file = "attrs-21.2.0.tar.gz", hash = "sha256:ef6aaac3ca6cd92904cdd0d83f629a15f18053ec84e6432106f7a4d04ae4f5fb"}, 603 | ] 604 | black = [ 605 | {file = "black-21.8b0-py3-none-any.whl", hash = "sha256:2a0f9a8c2b2a60dbcf1ccb058842fb22bdbbcb2f32c6cc02d9578f90b92ce8b7"}, 606 | {file = "black-21.8b0.tar.gz", hash = "sha256:570608d28aa3af1792b98c4a337dbac6367877b47b12b88ab42095cfc1a627c2"}, 607 | ] 608 | cached-property = [ 609 | {file = "cached-property-1.5.2.tar.gz", hash = "sha256:9fa5755838eecbb2d234c3aa390bd80fbd3ac6b6869109bfc1b499f7bd89a130"}, 610 | {file = "cached_property-1.5.2-py2.py3-none-any.whl", hash = "sha256:df4f613cf7ad9a588cc381aaf4a512d26265ecebd5eb9e1ba12f1319eb85a6a0"}, 611 | ] 612 | click = [ 613 | {file = "click-8.0.1-py3-none-any.whl", hash = "sha256:fba402a4a47334742d782209a7c79bc448911afe1149d07bdabdf480b3e2f4b6"}, 614 | {file = "click-8.0.1.tar.gz", hash = "sha256:8c04c11192119b1ef78ea049e0a6f0463e4c48ef00a30160c704337586f3ad7a"}, 615 | ] 616 | colorama = [ 617 | {file = "colorama-0.4.4-py2.py3-none-any.whl", hash = "sha256:9f47eda37229f68eee03b24b9748937c7dc3868f906e8ba69fbcbdd3bc5dc3e2"}, 618 | {file = "colorama-0.4.4.tar.gz", hash = "sha256:5941b2b48a20143d2267e95b1c2a7603ce057ee39fd88e7329b0c292aa16869b"}, 619 | ] 620 | fastapi = [ 621 | {file = "fastapi-0.68.1-py3-none-any.whl", hash = "sha256:94d2820906c36b9b8303796fb7271337ec89c74223229e3cfcf056b5a7d59e23"}, 622 | {file = "fastapi-0.68.1.tar.gz", hash = "sha256:644bb815bae326575c4b2842469fb83053a4b974b82fa792ff9283d17fbbd99d"}, 623 | ] 624 | flake8 = [ 625 | {file = "flake8-3.9.2-py2.py3-none-any.whl", hash = "sha256:bf8fd333346d844f616e8d47905ef3a3384edae6b4e9beb0c5101e25e3110907"}, 626 | {file = "flake8-3.9.2.tar.gz", hash = "sha256:07528381786f2a6237b061f6e96610a4167b226cb926e2aa2b6b1d78057c576b"}, 627 | ] 628 | flake8-black = [ 629 | {file = "flake8-black-0.2.3.tar.gz", hash = "sha256:c199844bc1b559d91195ebe8620216f21ed67f2cc1ff6884294c91a0d2492684"}, 630 | {file = "flake8_black-0.2.3-py3-none-any.whl", hash = "sha256:cc080ba5b3773b69ba102b6617a00cc4ecbad8914109690cfda4d565ea435d96"}, 631 | ] 632 | flake8-bugbear = [ 633 | {file = "flake8-bugbear-21.4.3.tar.gz", hash = "sha256:2346c81f889955b39e4a368eb7d508de723d9de05716c287dc860a4073dc57e7"}, 634 | {file = "flake8_bugbear-21.4.3-py36.py37.py38-none-any.whl", hash = "sha256:4f305dca96be62bf732a218fe6f1825472a621d3452c5b994d8f89dae21dbafa"}, 635 | ] 636 | graphql-core = [ 637 | {file = "graphql-core-3.1.6.tar.gz", hash = "sha256:e65975b6a13878f9113a1fa5320760585b522d139944e005936b1b8358d0651a"}, 638 | {file = "graphql_core-3.1.6-py3-none-any.whl", hash = "sha256:c78d09596d347e1cffd266c5384abfedf43ed1eae08729773bebb3d527fe5a14"}, 639 | ] 640 | greenlet = [ 641 | {file = "greenlet-1.1.1-cp27-cp27m-macosx_10_14_x86_64.whl", hash = "sha256:476ba9435afaead4382fbab8f1882f75e3fb2285c35c9285abb3dd30237f9142"}, 642 | {file = "greenlet-1.1.1-cp27-cp27m-manylinux1_x86_64.whl", hash = "sha256:44556302c0ab376e37939fd0058e1f0db2e769580d340fb03b01678d1ff25f68"}, 643 | {file = "greenlet-1.1.1-cp27-cp27m-manylinux2010_x86_64.whl", hash = "sha256:40abb7fec4f6294225d2b5464bb6d9552050ded14a7516588d6f010e7e366dcc"}, 644 | {file = "greenlet-1.1.1-cp27-cp27m-win32.whl", hash = "sha256:a11b6199a0b9dc868990456a2667167d0ba096c5224f6258e452bfbe5a9742c5"}, 645 | {file = "greenlet-1.1.1-cp27-cp27m-win_amd64.whl", hash = "sha256:e22a82d2b416d9227a500c6860cf13e74060cf10e7daf6695cbf4e6a94e0eee4"}, 646 | {file = "greenlet-1.1.1-cp27-cp27mu-manylinux1_x86_64.whl", hash = "sha256:bad269e442f1b7ffa3fa8820b3c3aa66f02a9f9455b5ba2db5a6f9eea96f56de"}, 647 | {file = "greenlet-1.1.1-cp27-cp27mu-manylinux2010_x86_64.whl", hash = "sha256:8ddb38fb6ad96c2ef7468ff73ba5c6876b63b664eebb2c919c224261ae5e8378"}, 648 | {file = "greenlet-1.1.1-cp310-cp310-macosx_10_14_x86_64.whl", hash = "sha256:84782c80a433d87530ae3f4b9ed58d4a57317d9918dfcc6a59115fa2d8731f2c"}, 649 | {file = "greenlet-1.1.1-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:ac991947ca6533ada4ce7095f0e28fe25d5b2f3266ad5b983ed4201e61596acf"}, 650 | {file = "greenlet-1.1.1-cp310-cp310-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:5317701c7ce167205c0569c10abc4bd01c7f4cf93f642c39f2ce975fa9b78a3c"}, 651 | {file = "greenlet-1.1.1-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:4870b018ca685ff573edd56b93f00a122f279640732bb52ce3a62b73ee5c4a92"}, 652 | {file = "greenlet-1.1.1-cp310-cp310-win_amd64.whl", hash = "sha256:990e0f5e64bcbc6bdbd03774ecb72496224d13b664aa03afd1f9b171a3269272"}, 653 | {file = "greenlet-1.1.1-cp35-cp35m-macosx_10_14_x86_64.whl", hash = "sha256:a414f8e14aa7bacfe1578f17c11d977e637d25383b6210587c29210af995ef04"}, 654 | {file = "greenlet-1.1.1-cp35-cp35m-manylinux1_x86_64.whl", hash = "sha256:e02780da03f84a671bb4205c5968c120f18df081236d7b5462b380fd4f0b497b"}, 655 | {file = "greenlet-1.1.1-cp35-cp35m-manylinux2010_x86_64.whl", hash = "sha256:dfcb5a4056e161307d103bc013478892cfd919f1262c2bb8703220adcb986362"}, 656 | {file = "greenlet-1.1.1-cp35-cp35m-win32.whl", hash = "sha256:655ab836324a473d4cd8cf231a2d6f283ed71ed77037679da554e38e606a7117"}, 657 | {file = "greenlet-1.1.1-cp35-cp35m-win_amd64.whl", hash = "sha256:6ce9d0784c3c79f3e5c5c9c9517bbb6c7e8aa12372a5ea95197b8a99402aa0e6"}, 658 | {file = "greenlet-1.1.1-cp36-cp36m-macosx_10_14_x86_64.whl", hash = "sha256:3fc6a447735749d651d8919da49aab03c434a300e9f0af1c886d560405840fd1"}, 659 | {file = "greenlet-1.1.1-cp36-cp36m-manylinux1_x86_64.whl", hash = "sha256:8039f5fe8030c43cd1732d9a234fdcbf4916fcc32e21745ca62e75023e4d4649"}, 660 | {file = "greenlet-1.1.1-cp36-cp36m-manylinux2010_x86_64.whl", hash = "sha256:fddfb31aa2ac550b938d952bca8a87f1db0f8dc930ffa14ce05b5c08d27e7fd1"}, 661 | {file = "greenlet-1.1.1-cp36-cp36m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:b97a807437b81f90f85022a9dcfd527deea38368a3979ccb49d93c9198b2c722"}, 662 | {file = "greenlet-1.1.1-cp36-cp36m-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:cf31e894dabb077a35bbe6963285d4515a387ff657bd25b0530c7168e48f167f"}, 663 | {file = "greenlet-1.1.1-cp36-cp36m-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:4eae94de9924bbb4d24960185363e614b1b62ff797c23dc3c8a7c75bbb8d187e"}, 664 | {file = "greenlet-1.1.1-cp36-cp36m-win32.whl", hash = "sha256:c1862f9f1031b1dee3ff00f1027fcd098ffc82120f43041fe67804b464bbd8a7"}, 665 | {file = "greenlet-1.1.1-cp36-cp36m-win_amd64.whl", hash = "sha256:9b02e6039eafd75e029d8c58b7b1f3e450ca563ef1fe21c7e3e40b9936c8d03e"}, 666 | {file = "greenlet-1.1.1-cp37-cp37m-macosx_10_14_x86_64.whl", hash = "sha256:84488516639c3c5e5c0e52f311fff94ebc45b56788c2a3bfe9cf8e75670f4de3"}, 667 | {file = "greenlet-1.1.1-cp37-cp37m-manylinux1_x86_64.whl", hash = "sha256:3f8fc59bc5d64fa41f58b0029794f474223693fd00016b29f4e176b3ee2cfd9f"}, 668 | {file = "greenlet-1.1.1-cp37-cp37m-manylinux2010_x86_64.whl", hash = "sha256:3e594015a2349ec6dcceda9aca29da8dc89e85b56825b7d1f138a3f6bb79dd4c"}, 669 | {file = "greenlet-1.1.1-cp37-cp37m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:e41f72f225192d5d4df81dad2974a8943b0f2d664a2a5cfccdf5a01506f5523c"}, 670 | {file = "greenlet-1.1.1-cp37-cp37m-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:75ff270fd05125dce3303e9216ccddc541a9e072d4fc764a9276d44dee87242b"}, 671 | {file = "greenlet-1.1.1-cp37-cp37m-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:5cde7ee190196cbdc078511f4df0be367af85636b84d8be32230f4871b960687"}, 672 | {file = "greenlet-1.1.1-cp37-cp37m-win32.whl", hash = "sha256:f253dad38605486a4590f9368ecbace95865fea0f2b66615d121ac91fd1a1563"}, 673 | {file = "greenlet-1.1.1-cp37-cp37m-win_amd64.whl", hash = "sha256:a91ee268f059583176c2c8b012a9fce7e49ca6b333a12bbc2dd01fc1a9783885"}, 674 | {file = "greenlet-1.1.1-cp38-cp38-macosx_10_14_x86_64.whl", hash = "sha256:34e6675167a238bede724ee60fe0550709e95adaff6a36bcc97006c365290384"}, 675 | {file = "greenlet-1.1.1-cp38-cp38-manylinux1_x86_64.whl", hash = "sha256:bf3725d79b1ceb19e83fb1aed44095518c0fcff88fba06a76c0891cfd1f36837"}, 676 | {file = "greenlet-1.1.1-cp38-cp38-manylinux2010_x86_64.whl", hash = "sha256:5c3b735ccf8fc8048664ee415f8af5a3a018cc92010a0d7195395059b4b39b7d"}, 677 | {file = "greenlet-1.1.1-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:e2002a59453858c7f3404690ae80f10c924a39f45f6095f18a985a1234c37334"}, 678 | {file = "greenlet-1.1.1-cp38-cp38-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:04e1849c88aa56584d4a0a6e36af5ec7cc37993fdc1fda72b56aa1394a92ded3"}, 679 | {file = "greenlet-1.1.1-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:c8d4ed48eed7414ccb2aaaecbc733ed2a84c299714eae3f0f48db085342d5629"}, 680 | {file = "greenlet-1.1.1-cp38-cp38-win32.whl", hash = "sha256:2f89d74b4f423e756a018832cd7a0a571e0a31b9ca59323b77ce5f15a437629b"}, 681 | {file = "greenlet-1.1.1-cp38-cp38-win_amd64.whl", hash = "sha256:d15cb6f8706678dc47fb4e4f8b339937b04eda48a0af1cca95f180db552e7663"}, 682 | {file = "greenlet-1.1.1-cp39-cp39-macosx_10_14_x86_64.whl", hash = "sha256:b050dbb96216db273b56f0e5960959c2b4cb679fe1e58a0c3906fa0a60c00662"}, 683 | {file = "greenlet-1.1.1-cp39-cp39-manylinux1_x86_64.whl", hash = "sha256:6e0696525500bc8aa12eae654095d2260db4dc95d5c35af2b486eae1bf914ccd"}, 684 | {file = "greenlet-1.1.1-cp39-cp39-manylinux2010_x86_64.whl", hash = "sha256:07e6d88242e09b399682b39f8dfa1e7e6eca66b305de1ff74ed9eb1a7d8e539c"}, 685 | {file = "greenlet-1.1.1-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:98b491976ed656be9445b79bc57ed21decf08a01aaaf5fdabf07c98c108111f6"}, 686 | {file = "greenlet-1.1.1-cp39-cp39-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:05e72db813c28906cdc59bd0da7c325d9b82aa0b0543014059c34c8c4ad20e16"}, 687 | {file = "greenlet-1.1.1-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:090126004c8ab9cd0787e2acf63d79e80ab41a18f57d6448225bbfcba475034f"}, 688 | {file = "greenlet-1.1.1-cp39-cp39-win32.whl", hash = "sha256:1796f2c283faab2b71c67e9b9aefb3f201fdfbee5cb55001f5ffce9125f63a45"}, 689 | {file = "greenlet-1.1.1-cp39-cp39-win_amd64.whl", hash = "sha256:4adaf53ace289ced90797d92d767d37e7cdc29f13bd3830c3f0a561277a4ae83"}, 690 | {file = "greenlet-1.1.1.tar.gz", hash = "sha256:c0f22774cd8294078bdf7392ac73cf00bfa1e5e0ed644bd064fdabc5f2a2f481"}, 691 | ] 692 | h11 = [ 693 | {file = "h11-0.12.0-py3-none-any.whl", hash = "sha256:36a3cb8c0a032f56e2da7084577878a035d3b61d104230d4bd49c0c6b555a9c6"}, 694 | {file = "h11-0.12.0.tar.gz", hash = "sha256:47222cb6067e4a307d535814917cd98fd0a57b6788ce715755fa2b6c28b56042"}, 695 | ] 696 | httptools = [ 697 | {file = "httptools-0.2.0-cp35-cp35m-macosx_10_14_x86_64.whl", hash = "sha256:79dbc21f3612a78b28384e989b21872e2e3cf3968532601544696e4ed0007ce5"}, 698 | {file = "httptools-0.2.0-cp35-cp35m-manylinux1_x86_64.whl", hash = "sha256:78d03dd39b09c99ec917d50189e6743adbfd18c15d5944392d2eabda688bf149"}, 699 | {file = "httptools-0.2.0-cp36-cp36m-macosx_10_14_x86_64.whl", hash = "sha256:a23166e5ae2775709cf4f7ad4c2048755ebfb272767d244e1a96d55ac775cca7"}, 700 | {file = "httptools-0.2.0-cp36-cp36m-manylinux1_x86_64.whl", hash = "sha256:3ab1f390d8867f74b3b5ee2a7ecc9b8d7f53750bd45714bf1cb72a953d7dfa77"}, 701 | {file = "httptools-0.2.0-cp36-cp36m-win_amd64.whl", hash = "sha256:a7594f9a010cdf1e16a58b3bf26c9da39bbf663e3b8d46d39176999d71816658"}, 702 | {file = "httptools-0.2.0-cp37-cp37m-macosx_10_14_x86_64.whl", hash = "sha256:01b392a166adcc8bc2f526a939a8aabf89fe079243e1543fd0e7dc1b58d737cb"}, 703 | {file = "httptools-0.2.0-cp37-cp37m-manylinux1_x86_64.whl", hash = "sha256:80ffa04fe8c8dfacf6e4cef8277347d35b0442c581f5814f3b0cf41b65c43c6e"}, 704 | {file = "httptools-0.2.0-cp37-cp37m-win_amd64.whl", hash = "sha256:d5682eeb10cca0606c4a8286a3391d4c3c5a36f0c448e71b8bd05be4e1694bfb"}, 705 | {file = "httptools-0.2.0-cp38-cp38-macosx_10_14_x86_64.whl", hash = "sha256:a289c27ccae399a70eacf32df9a44059ca2ba4ac444604b00a19a6c1f0809943"}, 706 | {file = "httptools-0.2.0-cp38-cp38-manylinux1_x86_64.whl", hash = "sha256:813871f961edea6cb2fe312f2d9b27d12a51ba92545380126f80d0de1917ea15"}, 707 | {file = "httptools-0.2.0-cp38-cp38-win_amd64.whl", hash = "sha256:cc9be041e428c10f8b6ab358c6b393648f9457094e1dcc11b4906026d43cd380"}, 708 | {file = "httptools-0.2.0-cp39-cp39-macosx_10_14_x86_64.whl", hash = "sha256:b08d00d889a118f68f37f3c43e359aab24ee29eb2e3fe96d64c6a2ba8b9d6557"}, 709 | {file = "httptools-0.2.0-cp39-cp39-manylinux1_x86_64.whl", hash = "sha256:fd3b8905e21431ad306eeaf56644a68fdd621bf8f3097eff54d0f6bdf7262065"}, 710 | {file = "httptools-0.2.0-cp39-cp39-win_amd64.whl", hash = "sha256:200fc1cdf733a9ff554c0bb97a4047785cfaad9875307d6087001db3eb2b417f"}, 711 | {file = "httptools-0.2.0.tar.gz", hash = "sha256:94505026be56652d7a530ab03d89474dc6021019d6b8682281977163b3471ea0"}, 712 | ] 713 | importlib-metadata = [ 714 | {file = "importlib_metadata-4.8.1-py3-none-any.whl", hash = "sha256:b618b6d2d5ffa2f16add5697cf57a46c76a56229b0ed1c438322e4e95645bd15"}, 715 | {file = "importlib_metadata-4.8.1.tar.gz", hash = "sha256:f284b3e11256ad1e5d03ab86bb2ccd6f5339688ff17a4d797a0fe7df326f23b1"}, 716 | ] 717 | importlib-resources = [ 718 | {file = "importlib_resources-5.2.2-py3-none-any.whl", hash = "sha256:2480d8e07d1890056cb53c96e3de44fead9c62f2ba949b0f2e4c4345f4afa977"}, 719 | {file = "importlib_resources-5.2.2.tar.gz", hash = "sha256:a65882a4d0fe5fbf702273456ba2ce74fe44892c25e42e057aca526b702a6d4b"}, 720 | ] 721 | mako = [ 722 | {file = "Mako-1.1.5-py2.py3-none-any.whl", hash = "sha256:6804ee66a7f6a6416910463b00d76a7b25194cd27f1918500c5bd7be2a088a23"}, 723 | {file = "Mako-1.1.5.tar.gz", hash = "sha256:169fa52af22a91900d852e937400e79f535496191c63712e3b9fda5a9bed6fc3"}, 724 | ] 725 | markupsafe = [ 726 | {file = "MarkupSafe-2.0.1-cp310-cp310-macosx_10_9_universal2.whl", hash = "sha256:d8446c54dc28c01e5a2dbac5a25f071f6653e6e40f3a8818e8b45d790fe6ef53"}, 727 | {file = "MarkupSafe-2.0.1-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:36bc903cbb393720fad60fc28c10de6acf10dc6cc883f3e24ee4012371399a38"}, 728 | {file = "MarkupSafe-2.0.1-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:2d7d807855b419fc2ed3e631034685db6079889a1f01d5d9dac950f764da3dad"}, 729 | {file = "MarkupSafe-2.0.1-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.manylinux_2_12_i686.manylinux2010_i686.whl", hash = "sha256:add36cb2dbb8b736611303cd3bfcee00afd96471b09cda130da3581cbdc56a6d"}, 730 | {file = "MarkupSafe-2.0.1-cp310-cp310-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:168cd0a3642de83558a5153c8bd34f175a9a6e7f6dc6384b9655d2697312a646"}, 731 | {file = "MarkupSafe-2.0.1-cp310-cp310-win32.whl", hash = "sha256:99df47edb6bda1249d3e80fdabb1dab8c08ef3975f69aed437cb69d0a5de1e28"}, 732 | {file = "MarkupSafe-2.0.1-cp310-cp310-win_amd64.whl", hash = "sha256:e0f138900af21926a02425cf736db95be9f4af72ba1bb21453432a07f6082134"}, 733 | {file = "MarkupSafe-2.0.1-cp36-cp36m-macosx_10_9_x86_64.whl", hash = "sha256:f9081981fe268bd86831e5c75f7de206ef275defcb82bc70740ae6dc507aee51"}, 734 | {file = "MarkupSafe-2.0.1-cp36-cp36m-manylinux1_i686.whl", hash = "sha256:0955295dd5eec6cb6cc2fe1698f4c6d84af2e92de33fbcac4111913cd100a6ff"}, 735 | {file = "MarkupSafe-2.0.1-cp36-cp36m-manylinux1_x86_64.whl", hash = "sha256:0446679737af14f45767963a1a9ef7620189912317d095f2d9ffa183a4d25d2b"}, 736 | {file = "MarkupSafe-2.0.1-cp36-cp36m-manylinux2010_i686.whl", hash = "sha256:f826e31d18b516f653fe296d967d700fddad5901ae07c622bb3705955e1faa94"}, 737 | {file = "MarkupSafe-2.0.1-cp36-cp36m-manylinux2010_x86_64.whl", hash = "sha256:fa130dd50c57d53368c9d59395cb5526eda596d3ffe36666cd81a44d56e48872"}, 738 | {file = "MarkupSafe-2.0.1-cp36-cp36m-manylinux2014_aarch64.whl", hash = "sha256:905fec760bd2fa1388bb5b489ee8ee5f7291d692638ea5f67982d968366bef9f"}, 739 | {file = "MarkupSafe-2.0.1-cp36-cp36m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:bf5d821ffabf0ef3533c39c518f3357b171a1651c1ff6827325e4489b0e46c3c"}, 740 | {file = "MarkupSafe-2.0.1-cp36-cp36m-manylinux_2_5_i686.manylinux1_i686.manylinux_2_12_i686.manylinux2010_i686.whl", hash = "sha256:0d4b31cc67ab36e3392bbf3862cfbadac3db12bdd8b02a2731f509ed5b829724"}, 741 | {file = "MarkupSafe-2.0.1-cp36-cp36m-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:baa1a4e8f868845af802979fcdbf0bb11f94f1cb7ced4c4b8a351bb60d108145"}, 742 | {file = "MarkupSafe-2.0.1-cp36-cp36m-win32.whl", hash = "sha256:6c4ca60fa24e85fe25b912b01e62cb969d69a23a5d5867682dd3e80b5b02581d"}, 743 | {file = "MarkupSafe-2.0.1-cp36-cp36m-win_amd64.whl", hash = "sha256:b2f4bf27480f5e5e8ce285a8c8fd176c0b03e93dcc6646477d4630e83440c6a9"}, 744 | {file = "MarkupSafe-2.0.1-cp37-cp37m-macosx_10_9_x86_64.whl", hash = "sha256:0717a7390a68be14b8c793ba258e075c6f4ca819f15edfc2a3a027c823718567"}, 745 | {file = "MarkupSafe-2.0.1-cp37-cp37m-manylinux1_i686.whl", hash = "sha256:6557b31b5e2c9ddf0de32a691f2312a32f77cd7681d8af66c2692efdbef84c18"}, 746 | {file = "MarkupSafe-2.0.1-cp37-cp37m-manylinux1_x86_64.whl", hash = "sha256:49e3ceeabbfb9d66c3aef5af3a60cc43b85c33df25ce03d0031a608b0a8b2e3f"}, 747 | {file = "MarkupSafe-2.0.1-cp37-cp37m-manylinux2010_i686.whl", hash = "sha256:d7f9850398e85aba693bb640262d3611788b1f29a79f0c93c565694658f4071f"}, 748 | {file = "MarkupSafe-2.0.1-cp37-cp37m-manylinux2010_x86_64.whl", hash = "sha256:6a7fae0dd14cf60ad5ff42baa2e95727c3d81ded453457771d02b7d2b3f9c0c2"}, 749 | {file = "MarkupSafe-2.0.1-cp37-cp37m-manylinux2014_aarch64.whl", hash = "sha256:b7f2d075102dc8c794cbde1947378051c4e5180d52d276987b8d28a3bd58c17d"}, 750 | {file = "MarkupSafe-2.0.1-cp37-cp37m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:e9936f0b261d4df76ad22f8fee3ae83b60d7c3e871292cd42f40b81b70afae85"}, 751 | {file = "MarkupSafe-2.0.1-cp37-cp37m-manylinux_2_5_i686.manylinux1_i686.manylinux_2_12_i686.manylinux2010_i686.whl", hash = "sha256:2a7d351cbd8cfeb19ca00de495e224dea7e7d919659c2841bbb7f420ad03e2d6"}, 752 | {file = "MarkupSafe-2.0.1-cp37-cp37m-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:60bf42e36abfaf9aff1f50f52644b336d4f0a3fd6d8a60ca0d054ac9f713a864"}, 753 | {file = "MarkupSafe-2.0.1-cp37-cp37m-win32.whl", hash = "sha256:a30e67a65b53ea0a5e62fe23682cfe22712e01f453b95233b25502f7c61cb415"}, 754 | {file = "MarkupSafe-2.0.1-cp37-cp37m-win_amd64.whl", hash = "sha256:611d1ad9a4288cf3e3c16014564df047fe08410e628f89805e475368bd304914"}, 755 | {file = "MarkupSafe-2.0.1-cp38-cp38-macosx_10_9_universal2.whl", hash = "sha256:5bb28c636d87e840583ee3adeb78172efc47c8b26127267f54a9c0ec251d41a9"}, 756 | {file = "MarkupSafe-2.0.1-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:be98f628055368795d818ebf93da628541e10b75b41c559fdf36d104c5787066"}, 757 | {file = "MarkupSafe-2.0.1-cp38-cp38-manylinux1_i686.whl", hash = "sha256:1d609f577dc6e1aa17d746f8bd3c31aa4d258f4070d61b2aa5c4166c1539de35"}, 758 | {file = "MarkupSafe-2.0.1-cp38-cp38-manylinux1_x86_64.whl", hash = "sha256:7d91275b0245b1da4d4cfa07e0faedd5b0812efc15b702576d103293e252af1b"}, 759 | {file = "MarkupSafe-2.0.1-cp38-cp38-manylinux2010_i686.whl", hash = "sha256:01a9b8ea66f1658938f65b93a85ebe8bc016e6769611be228d797c9d998dd298"}, 760 | {file = "MarkupSafe-2.0.1-cp38-cp38-manylinux2010_x86_64.whl", hash = "sha256:47ab1e7b91c098ab893b828deafa1203de86d0bc6ab587b160f78fe6c4011f75"}, 761 | {file = "MarkupSafe-2.0.1-cp38-cp38-manylinux2014_aarch64.whl", hash = "sha256:97383d78eb34da7e1fa37dd273c20ad4320929af65d156e35a5e2d89566d9dfb"}, 762 | {file = "MarkupSafe-2.0.1-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:6fcf051089389abe060c9cd7caa212c707e58153afa2c649f00346ce6d260f1b"}, 763 | {file = "MarkupSafe-2.0.1-cp38-cp38-manylinux_2_5_i686.manylinux1_i686.manylinux_2_12_i686.manylinux2010_i686.whl", hash = "sha256:5855f8438a7d1d458206a2466bf82b0f104a3724bf96a1c781ab731e4201731a"}, 764 | {file = "MarkupSafe-2.0.1-cp38-cp38-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:3dd007d54ee88b46be476e293f48c85048603f5f516008bee124ddd891398ed6"}, 765 | {file = "MarkupSafe-2.0.1-cp38-cp38-win32.whl", hash = "sha256:023cb26ec21ece8dc3907c0e8320058b2e0cb3c55cf9564da612bc325bed5e64"}, 766 | {file = "MarkupSafe-2.0.1-cp38-cp38-win_amd64.whl", hash = "sha256:984d76483eb32f1bcb536dc27e4ad56bba4baa70be32fa87152832cdd9db0833"}, 767 | {file = "MarkupSafe-2.0.1-cp39-cp39-macosx_10_9_universal2.whl", hash = "sha256:2ef54abee730b502252bcdf31b10dacb0a416229b72c18b19e24a4509f273d26"}, 768 | {file = "MarkupSafe-2.0.1-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:3c112550557578c26af18a1ccc9e090bfe03832ae994343cfdacd287db6a6ae7"}, 769 | {file = "MarkupSafe-2.0.1-cp39-cp39-manylinux1_i686.whl", hash = "sha256:53edb4da6925ad13c07b6d26c2a852bd81e364f95301c66e930ab2aef5b5ddd8"}, 770 | {file = "MarkupSafe-2.0.1-cp39-cp39-manylinux1_x86_64.whl", hash = "sha256:f5653a225f31e113b152e56f154ccbe59eeb1c7487b39b9d9f9cdb58e6c79dc5"}, 771 | {file = "MarkupSafe-2.0.1-cp39-cp39-manylinux2010_i686.whl", hash = "sha256:4efca8f86c54b22348a5467704e3fec767b2db12fc39c6d963168ab1d3fc9135"}, 772 | {file = "MarkupSafe-2.0.1-cp39-cp39-manylinux2010_x86_64.whl", hash = "sha256:ab3ef638ace319fa26553db0624c4699e31a28bb2a835c5faca8f8acf6a5a902"}, 773 | {file = "MarkupSafe-2.0.1-cp39-cp39-manylinux2014_aarch64.whl", hash = "sha256:f8ba0e8349a38d3001fae7eadded3f6606f0da5d748ee53cc1dab1d6527b9509"}, 774 | {file = "MarkupSafe-2.0.1-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:c47adbc92fc1bb2b3274c4b3a43ae0e4573d9fbff4f54cd484555edbf030baf1"}, 775 | {file = "MarkupSafe-2.0.1-cp39-cp39-manylinux_2_5_i686.manylinux1_i686.manylinux_2_12_i686.manylinux2010_i686.whl", hash = "sha256:37205cac2a79194e3750b0af2a5720d95f786a55ce7df90c3af697bfa100eaac"}, 776 | {file = "MarkupSafe-2.0.1-cp39-cp39-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:1f2ade76b9903f39aa442b4aadd2177decb66525062db244b35d71d0ee8599b6"}, 777 | {file = "MarkupSafe-2.0.1-cp39-cp39-win32.whl", hash = "sha256:10f82115e21dc0dfec9ab5c0223652f7197feb168c940f3ef61563fc2d6beb74"}, 778 | {file = "MarkupSafe-2.0.1-cp39-cp39-win_amd64.whl", hash = "sha256:693ce3f9e70a6cf7d2fb9e6c9d8b204b6b39897a2c4a1aa65728d5ac97dcc1d8"}, 779 | {file = "MarkupSafe-2.0.1.tar.gz", hash = "sha256:594c67807fb16238b30c44bdf74f36c02cdf22d1c8cda91ef8a0ed8dabf5620a"}, 780 | ] 781 | mccabe = [ 782 | {file = "mccabe-0.6.1-py2.py3-none-any.whl", hash = "sha256:ab8a6258860da4b6677da4bd2fe5dc2c659cff31b3ee4f7f5d64e79735b80d42"}, 783 | {file = "mccabe-0.6.1.tar.gz", hash = "sha256:dd8d182285a0fe56bace7f45b5e7d1a6ebcbf524e8f3bd87eb0f125271b8831f"}, 784 | ] 785 | mypy = [ 786 | {file = "mypy-0.910-cp35-cp35m-macosx_10_9_x86_64.whl", hash = "sha256:a155d80ea6cee511a3694b108c4494a39f42de11ee4e61e72bc424c490e46457"}, 787 | {file = "mypy-0.910-cp35-cp35m-manylinux1_x86_64.whl", hash = "sha256:b94e4b785e304a04ea0828759172a15add27088520dc7e49ceade7834275bedb"}, 788 | {file = "mypy-0.910-cp35-cp35m-manylinux2010_x86_64.whl", hash = "sha256:088cd9c7904b4ad80bec811053272986611b84221835e079be5bcad029e79dd9"}, 789 | {file = "mypy-0.910-cp35-cp35m-win_amd64.whl", hash = "sha256:adaeee09bfde366d2c13fe6093a7df5df83c9a2ba98638c7d76b010694db760e"}, 790 | {file = "mypy-0.910-cp36-cp36m-macosx_10_9_x86_64.whl", hash = "sha256:ecd2c3fe726758037234c93df7e98deb257fd15c24c9180dacf1ef829da5f921"}, 791 | {file = "mypy-0.910-cp36-cp36m-manylinux1_x86_64.whl", hash = "sha256:d9dd839eb0dc1bbe866a288ba3c1afc33a202015d2ad83b31e875b5905a079b6"}, 792 | {file = "mypy-0.910-cp36-cp36m-manylinux2010_x86_64.whl", hash = "sha256:3e382b29f8e0ccf19a2df2b29a167591245df90c0b5a2542249873b5c1d78212"}, 793 | {file = "mypy-0.910-cp36-cp36m-win_amd64.whl", hash = "sha256:53fd2eb27a8ee2892614370896956af2ff61254c275aaee4c230ae771cadd885"}, 794 | {file = "mypy-0.910-cp37-cp37m-macosx_10_9_x86_64.whl", hash = "sha256:b6fb13123aeef4a3abbcfd7e71773ff3ff1526a7d3dc538f3929a49b42be03f0"}, 795 | {file = "mypy-0.910-cp37-cp37m-manylinux1_x86_64.whl", hash = "sha256:e4dab234478e3bd3ce83bac4193b2ecd9cf94e720ddd95ce69840273bf44f6de"}, 796 | {file = "mypy-0.910-cp37-cp37m-manylinux2010_x86_64.whl", hash = "sha256:7df1ead20c81371ccd6091fa3e2878559b5c4d4caadaf1a484cf88d93ca06703"}, 797 | {file = "mypy-0.910-cp37-cp37m-win_amd64.whl", hash = "sha256:0aadfb2d3935988ec3815952e44058a3100499f5be5b28c34ac9d79f002a4a9a"}, 798 | {file = "mypy-0.910-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:ec4e0cd079db280b6bdabdc807047ff3e199f334050db5cbb91ba3e959a67504"}, 799 | {file = "mypy-0.910-cp38-cp38-manylinux1_x86_64.whl", hash = "sha256:119bed3832d961f3a880787bf621634ba042cb8dc850a7429f643508eeac97b9"}, 800 | {file = "mypy-0.910-cp38-cp38-manylinux2010_x86_64.whl", hash = "sha256:866c41f28cee548475f146aa4d39a51cf3b6a84246969f3759cb3e9c742fc072"}, 801 | {file = "mypy-0.910-cp38-cp38-win_amd64.whl", hash = "sha256:ceb6e0a6e27fb364fb3853389607cf7eb3a126ad335790fa1e14ed02fba50811"}, 802 | {file = "mypy-0.910-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:1a85e280d4d217150ce8cb1a6dddffd14e753a4e0c3cf90baabb32cefa41b59e"}, 803 | {file = "mypy-0.910-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:42c266ced41b65ed40a282c575705325fa7991af370036d3f134518336636f5b"}, 804 | {file = "mypy-0.910-cp39-cp39-manylinux1_x86_64.whl", hash = "sha256:3c4b8ca36877fc75339253721f69603a9c7fdb5d4d5a95a1a1b899d8b86a4de2"}, 805 | {file = "mypy-0.910-cp39-cp39-manylinux2010_x86_64.whl", hash = "sha256:c0df2d30ed496a08de5daed2a9ea807d07c21ae0ab23acf541ab88c24b26ab97"}, 806 | {file = "mypy-0.910-cp39-cp39-win_amd64.whl", hash = "sha256:c6c2602dffb74867498f86e6129fd52a2770c48b7cd3ece77ada4fa38f94eba8"}, 807 | {file = "mypy-0.910-py3-none-any.whl", hash = "sha256:ef565033fa5a958e62796867b1df10c40263ea9ded87164d67572834e57a174d"}, 808 | {file = "mypy-0.910.tar.gz", hash = "sha256:704098302473cb31a218f1775a873b376b30b4c18229421e9e9dc8916fd16150"}, 809 | ] 810 | mypy-extensions = [ 811 | {file = "mypy_extensions-0.4.3-py2.py3-none-any.whl", hash = "sha256:090fedd75945a69ae91ce1303b5824f428daf5a028d2f6ab8a299250a846f15d"}, 812 | {file = "mypy_extensions-0.4.3.tar.gz", hash = "sha256:2d82818f5bb3e369420cb3c4060a7970edba416647068eb4c5343488a6c604a8"}, 813 | ] 814 | pathspec = [ 815 | {file = "pathspec-0.9.0-py2.py3-none-any.whl", hash = "sha256:7d15c4ddb0b5c802d161efc417ec1a2558ea2653c2e8ad9c19098201dc1c993a"}, 816 | {file = "pathspec-0.9.0.tar.gz", hash = "sha256:e564499435a2673d586f6b2130bb5b95f04a3ba06f81b8f895b651a3c76aabb1"}, 817 | ] 818 | platformdirs = [ 819 | {file = "platformdirs-2.3.0-py3-none-any.whl", hash = "sha256:8003ac87717ae2c7ee1ea5a84a1a61e87f3fbd16eb5aadba194ea30a9019f648"}, 820 | {file = "platformdirs-2.3.0.tar.gz", hash = "sha256:15b056538719b1c94bdaccb29e5f81879c7f7f0f4a153f46086d155dffcd4f0f"}, 821 | ] 822 | pycodestyle = [ 823 | {file = "pycodestyle-2.7.0-py2.py3-none-any.whl", hash = "sha256:514f76d918fcc0b55c6680472f0a37970994e07bbb80725808c17089be302068"}, 824 | {file = "pycodestyle-2.7.0.tar.gz", hash = "sha256:c389c1d06bf7904078ca03399a4816f974a1d590090fecea0c63ec26ebaf1cef"}, 825 | ] 826 | pydantic = [ 827 | {file = "pydantic-1.8.2-cp36-cp36m-macosx_10_9_x86_64.whl", hash = "sha256:05ddfd37c1720c392f4e0d43c484217b7521558302e7069ce8d318438d297739"}, 828 | {file = "pydantic-1.8.2-cp36-cp36m-manylinux1_i686.whl", hash = "sha256:a7c6002203fe2c5a1b5cbb141bb85060cbff88c2d78eccbc72d97eb7022c43e4"}, 829 | {file = "pydantic-1.8.2-cp36-cp36m-manylinux2014_i686.whl", hash = "sha256:589eb6cd6361e8ac341db97602eb7f354551482368a37f4fd086c0733548308e"}, 830 | {file = "pydantic-1.8.2-cp36-cp36m-manylinux2014_x86_64.whl", hash = "sha256:10e5622224245941efc193ad1d159887872776df7a8fd592ed746aa25d071840"}, 831 | {file = "pydantic-1.8.2-cp36-cp36m-win_amd64.whl", hash = "sha256:99a9fc39470010c45c161a1dc584997f1feb13f689ecf645f59bb4ba623e586b"}, 832 | {file = "pydantic-1.8.2-cp37-cp37m-macosx_10_9_x86_64.whl", hash = "sha256:a83db7205f60c6a86f2c44a61791d993dff4b73135df1973ecd9eed5ea0bda20"}, 833 | {file = "pydantic-1.8.2-cp37-cp37m-manylinux1_i686.whl", hash = "sha256:41b542c0b3c42dc17da70554bc6f38cbc30d7066d2c2815a94499b5684582ecb"}, 834 | {file = "pydantic-1.8.2-cp37-cp37m-manylinux2014_i686.whl", hash = "sha256:ea5cb40a3b23b3265f6325727ddfc45141b08ed665458be8c6285e7b85bd73a1"}, 835 | {file = "pydantic-1.8.2-cp37-cp37m-manylinux2014_x86_64.whl", hash = "sha256:18b5ea242dd3e62dbf89b2b0ec9ba6c7b5abaf6af85b95a97b00279f65845a23"}, 836 | {file = "pydantic-1.8.2-cp37-cp37m-win_amd64.whl", hash = "sha256:234a6c19f1c14e25e362cb05c68afb7f183eb931dd3cd4605eafff055ebbf287"}, 837 | {file = "pydantic-1.8.2-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:021ea0e4133e8c824775a0cfe098677acf6fa5a3cbf9206a376eed3fc09302cd"}, 838 | {file = "pydantic-1.8.2-cp38-cp38-manylinux1_i686.whl", hash = "sha256:e710876437bc07bd414ff453ac8ec63d219e7690128d925c6e82889d674bb505"}, 839 | {file = "pydantic-1.8.2-cp38-cp38-manylinux2014_i686.whl", hash = "sha256:ac8eed4ca3bd3aadc58a13c2aa93cd8a884bcf21cb019f8cfecaae3b6ce3746e"}, 840 | {file = "pydantic-1.8.2-cp38-cp38-manylinux2014_x86_64.whl", hash = "sha256:4a03cbbe743e9c7247ceae6f0d8898f7a64bb65800a45cbdc52d65e370570820"}, 841 | {file = "pydantic-1.8.2-cp38-cp38-win_amd64.whl", hash = "sha256:8621559dcf5afacf0069ed194278f35c255dc1a1385c28b32dd6c110fd6531b3"}, 842 | {file = "pydantic-1.8.2-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:8b223557f9510cf0bfd8b01316bf6dd281cf41826607eada99662f5e4963f316"}, 843 | {file = "pydantic-1.8.2-cp39-cp39-manylinux1_i686.whl", hash = "sha256:244ad78eeb388a43b0c927e74d3af78008e944074b7d0f4f696ddd5b2af43c62"}, 844 | {file = "pydantic-1.8.2-cp39-cp39-manylinux2014_i686.whl", hash = "sha256:05ef5246a7ffd2ce12a619cbb29f3307b7c4509307b1b49f456657b43529dc6f"}, 845 | {file = "pydantic-1.8.2-cp39-cp39-manylinux2014_x86_64.whl", hash = "sha256:54cd5121383f4a461ff7644c7ca20c0419d58052db70d8791eacbbe31528916b"}, 846 | {file = "pydantic-1.8.2-cp39-cp39-win_amd64.whl", hash = "sha256:4be75bebf676a5f0f87937c6ddb061fa39cbea067240d98e298508c1bda6f3f3"}, 847 | {file = "pydantic-1.8.2-py3-none-any.whl", hash = "sha256:fec866a0b59f372b7e776f2d7308511784dace622e0992a0b59ea3ccee0ae833"}, 848 | {file = "pydantic-1.8.2.tar.gz", hash = "sha256:26464e57ccaafe72b7ad156fdaa4e9b9ef051f69e175dbbb463283000c05ab7b"}, 849 | ] 850 | pyflakes = [ 851 | {file = "pyflakes-2.3.1-py2.py3-none-any.whl", hash = "sha256:7893783d01b8a89811dd72d7dfd4d84ff098e5eed95cfa8905b22bbffe52efc3"}, 852 | {file = "pyflakes-2.3.1.tar.gz", hash = "sha256:f5bc8ecabc05bb9d291eb5203d6810b49040f6ff446a756326104746cc00c1db"}, 853 | ] 854 | pygments = [ 855 | {file = "Pygments-2.10.0-py3-none-any.whl", hash = "sha256:b8e67fe6af78f492b3c4b3e2970c0624cbf08beb1e493b2c99b9fa1b67a20380"}, 856 | {file = "Pygments-2.10.0.tar.gz", hash = "sha256:f398865f7eb6874156579fdf36bc840a03cab64d1cde9e93d68f46a425ec52c6"}, 857 | ] 858 | python-dateutil = [ 859 | {file = "python-dateutil-2.8.2.tar.gz", hash = "sha256:0123cacc1627ae19ddf3c27a5de5bd67ee4586fbdd6440d9748f8abb483d3e86"}, 860 | {file = "python_dateutil-2.8.2-py2.py3-none-any.whl", hash = "sha256:961d03dc3453ebbc59dbdea9e4e11c5651520a876d0f4db161e8674aae935da9"}, 861 | ] 862 | python-dotenv = [ 863 | {file = "python-dotenv-0.19.0.tar.gz", hash = "sha256:f521bc2ac9a8e03c736f62911605c5d83970021e3fa95b37d769e2bbbe9b6172"}, 864 | {file = "python_dotenv-0.19.0-py2.py3-none-any.whl", hash = "sha256:aae25dc1ebe97c420f50b81fb0e5c949659af713f31fdb63c749ca68748f34b1"}, 865 | ] 866 | python-multipart = [ 867 | {file = "python-multipart-0.0.5.tar.gz", hash = "sha256:f7bb5f611fc600d15fa47b3974c8aa16e93724513b49b5f95c81e6624c83fa43"}, 868 | ] 869 | pyyaml = [ 870 | {file = "PyYAML-5.4.1-cp27-cp27m-macosx_10_9_x86_64.whl", hash = "sha256:3b2b1824fe7112845700f815ff6a489360226a5609b96ec2190a45e62a9fc922"}, 871 | {file = "PyYAML-5.4.1-cp27-cp27m-win32.whl", hash = "sha256:129def1b7c1bf22faffd67b8f3724645203b79d8f4cc81f674654d9902cb4393"}, 872 | {file = "PyYAML-5.4.1-cp27-cp27m-win_amd64.whl", hash = "sha256:4465124ef1b18d9ace298060f4eccc64b0850899ac4ac53294547536533800c8"}, 873 | {file = "PyYAML-5.4.1-cp27-cp27mu-manylinux1_x86_64.whl", hash = "sha256:bb4191dfc9306777bc594117aee052446b3fa88737cd13b7188d0e7aa8162185"}, 874 | {file = "PyYAML-5.4.1-cp36-cp36m-macosx_10_9_x86_64.whl", hash = "sha256:6c78645d400265a062508ae399b60b8c167bf003db364ecb26dcab2bda048253"}, 875 | {file = "PyYAML-5.4.1-cp36-cp36m-manylinux1_x86_64.whl", hash = "sha256:4e0583d24c881e14342eaf4ec5fbc97f934b999a6828693a99157fde912540cc"}, 876 | {file = "PyYAML-5.4.1-cp36-cp36m-manylinux2014_aarch64.whl", hash = "sha256:72a01f726a9c7851ca9bfad6fd09ca4e090a023c00945ea05ba1638c09dc3347"}, 877 | {file = "PyYAML-5.4.1-cp36-cp36m-manylinux2014_s390x.whl", hash = "sha256:895f61ef02e8fed38159bb70f7e100e00f471eae2bc838cd0f4ebb21e28f8541"}, 878 | {file = "PyYAML-5.4.1-cp36-cp36m-win32.whl", hash = "sha256:3bd0e463264cf257d1ffd2e40223b197271046d09dadf73a0fe82b9c1fc385a5"}, 879 | {file = "PyYAML-5.4.1-cp36-cp36m-win_amd64.whl", hash = "sha256:e4fac90784481d221a8e4b1162afa7c47ed953be40d31ab4629ae917510051df"}, 880 | {file = "PyYAML-5.4.1-cp37-cp37m-macosx_10_9_x86_64.whl", hash = "sha256:5accb17103e43963b80e6f837831f38d314a0495500067cb25afab2e8d7a4018"}, 881 | {file = "PyYAML-5.4.1-cp37-cp37m-manylinux1_x86_64.whl", hash = "sha256:e1d4970ea66be07ae37a3c2e48b5ec63f7ba6804bdddfdbd3cfd954d25a82e63"}, 882 | {file = "PyYAML-5.4.1-cp37-cp37m-manylinux2014_aarch64.whl", hash = "sha256:cb333c16912324fd5f769fff6bc5de372e9e7a202247b48870bc251ed40239aa"}, 883 | {file = "PyYAML-5.4.1-cp37-cp37m-manylinux2014_s390x.whl", hash = "sha256:fe69978f3f768926cfa37b867e3843918e012cf83f680806599ddce33c2c68b0"}, 884 | {file = "PyYAML-5.4.1-cp37-cp37m-win32.whl", hash = "sha256:dd5de0646207f053eb0d6c74ae45ba98c3395a571a2891858e87df7c9b9bd51b"}, 885 | {file = "PyYAML-5.4.1-cp37-cp37m-win_amd64.whl", hash = "sha256:08682f6b72c722394747bddaf0aa62277e02557c0fd1c42cb853016a38f8dedf"}, 886 | {file = "PyYAML-5.4.1-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:d2d9808ea7b4af864f35ea216be506ecec180628aced0704e34aca0b040ffe46"}, 887 | {file = "PyYAML-5.4.1-cp38-cp38-manylinux1_x86_64.whl", hash = "sha256:8c1be557ee92a20f184922c7b6424e8ab6691788e6d86137c5d93c1a6ec1b8fb"}, 888 | {file = "PyYAML-5.4.1-cp38-cp38-manylinux2014_aarch64.whl", hash = "sha256:fd7f6999a8070df521b6384004ef42833b9bd62cfee11a09bda1079b4b704247"}, 889 | {file = "PyYAML-5.4.1-cp38-cp38-manylinux2014_s390x.whl", hash = "sha256:bfb51918d4ff3d77c1c856a9699f8492c612cde32fd3bcd344af9be34999bfdc"}, 890 | {file = "PyYAML-5.4.1-cp38-cp38-win32.whl", hash = "sha256:fa5ae20527d8e831e8230cbffd9f8fe952815b2b7dae6ffec25318803a7528fc"}, 891 | {file = "PyYAML-5.4.1-cp38-cp38-win_amd64.whl", hash = "sha256:0f5f5786c0e09baddcd8b4b45f20a7b5d61a7e7e99846e3c799b05c7c53fa696"}, 892 | {file = "PyYAML-5.4.1-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:294db365efa064d00b8d1ef65d8ea2c3426ac366c0c4368d930bf1c5fb497f77"}, 893 | {file = "PyYAML-5.4.1-cp39-cp39-manylinux1_x86_64.whl", hash = "sha256:74c1485f7707cf707a7aef42ef6322b8f97921bd89be2ab6317fd782c2d53183"}, 894 | {file = "PyYAML-5.4.1-cp39-cp39-manylinux2014_aarch64.whl", hash = "sha256:d483ad4e639292c90170eb6f7783ad19490e7a8defb3e46f97dfe4bacae89122"}, 895 | {file = "PyYAML-5.4.1-cp39-cp39-manylinux2014_s390x.whl", hash = "sha256:fdc842473cd33f45ff6bce46aea678a54e3d21f1b61a7750ce3c498eedfe25d6"}, 896 | {file = "PyYAML-5.4.1-cp39-cp39-win32.whl", hash = "sha256:49d4cdd9065b9b6e206d0595fee27a96b5dd22618e7520c33204a4a3239d5b10"}, 897 | {file = "PyYAML-5.4.1-cp39-cp39-win_amd64.whl", hash = "sha256:c20cfa2d49991c8b4147af39859b167664f2ad4561704ee74c1de03318e898db"}, 898 | {file = "PyYAML-5.4.1.tar.gz", hash = "sha256:607774cbba28732bfa802b54baa7484215f530991055bb562efbed5b2f20a45e"}, 899 | ] 900 | regex = [ 901 | {file = "regex-2021.8.28-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:9d05ad5367c90814099000442b2125535e9d77581855b9bee8780f1b41f2b1a2"}, 902 | {file = "regex-2021.8.28-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:f3bf1bc02bc421047bfec3343729c4bbbea42605bcfd6d6bfe2c07ade8b12d2a"}, 903 | {file = "regex-2021.8.28-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:5f6a808044faae658f546dd5f525e921de9fa409de7a5570865467f03a626fc0"}, 904 | {file = "regex-2021.8.28-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.manylinux_2_12_i686.manylinux2010_i686.whl", hash = "sha256:a617593aeacc7a691cc4af4a4410031654f2909053bd8c8e7db837f179a630eb"}, 905 | {file = "regex-2021.8.28-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:79aef6b5cd41feff359acaf98e040844613ff5298d0d19c455b3d9ae0bc8c35a"}, 906 | {file = "regex-2021.8.28-cp310-cp310-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:0fc1f8f06977c2d4f5e3d3f0d4a08089be783973fc6b6e278bde01f0544ff308"}, 907 | {file = "regex-2021.8.28-cp310-cp310-win32.whl", hash = "sha256:6eebf512aa90751d5ef6a7c2ac9d60113f32e86e5687326a50d7686e309f66ed"}, 908 | {file = "regex-2021.8.28-cp310-cp310-win_amd64.whl", hash = "sha256:ac88856a8cbccfc14f1b2d0b829af354cc1743cb375e7f04251ae73b2af6adf8"}, 909 | {file = "regex-2021.8.28-cp36-cp36m-macosx_10_9_x86_64.whl", hash = "sha256:c206587c83e795d417ed3adc8453a791f6d36b67c81416676cad053b4104152c"}, 910 | {file = "regex-2021.8.28-cp36-cp36m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:e8690ed94481f219a7a967c118abaf71ccc440f69acd583cab721b90eeedb77c"}, 911 | {file = "regex-2021.8.28-cp36-cp36m-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:328a1fad67445550b982caa2a2a850da5989fd6595e858f02d04636e7f8b0b13"}, 912 | {file = "regex-2021.8.28-cp36-cp36m-manylinux_2_5_i686.manylinux1_i686.manylinux_2_12_i686.manylinux2010_i686.whl", hash = "sha256:c7cb4c512d2d3b0870e00fbbac2f291d4b4bf2634d59a31176a87afe2777c6f0"}, 913 | {file = "regex-2021.8.28-cp36-cp36m-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:66256b6391c057305e5ae9209941ef63c33a476b73772ca967d4a2df70520ec1"}, 914 | {file = "regex-2021.8.28-cp36-cp36m-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:8e44769068d33e0ea6ccdf4b84d80c5afffe5207aa4d1881a629cf0ef3ec398f"}, 915 | {file = "regex-2021.8.28-cp36-cp36m-win32.whl", hash = "sha256:08d74bfaa4c7731b8dac0a992c63673a2782758f7cfad34cf9c1b9184f911354"}, 916 | {file = "regex-2021.8.28-cp36-cp36m-win_amd64.whl", hash = "sha256:abb48494d88e8a82601af905143e0de838c776c1241d92021e9256d5515b3645"}, 917 | {file = "regex-2021.8.28-cp37-cp37m-macosx_10_9_x86_64.whl", hash = "sha256:b4c220a1fe0d2c622493b0a1fd48f8f991998fb447d3cd368033a4b86cf1127a"}, 918 | {file = "regex-2021.8.28-cp37-cp37m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:d4a332404baa6665b54e5d283b4262f41f2103c255897084ec8f5487ce7b9e8e"}, 919 | {file = "regex-2021.8.28-cp37-cp37m-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:c61dcc1cf9fd165127a2853e2c31eb4fb961a4f26b394ac9fe5669c7a6592892"}, 920 | {file = "regex-2021.8.28-cp37-cp37m-manylinux_2_5_i686.manylinux1_i686.manylinux_2_12_i686.manylinux2010_i686.whl", hash = "sha256:ee329d0387b5b41a5dddbb6243a21cb7896587a651bebb957e2d2bb8b63c0791"}, 921 | {file = "regex-2021.8.28-cp37-cp37m-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:f60667673ff9c249709160529ab39667d1ae9fd38634e006bec95611f632e759"}, 922 | {file = "regex-2021.8.28-cp37-cp37m-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:b844fb09bd9936ed158ff9df0ab601e2045b316b17aa8b931857365ea8586906"}, 923 | {file = "regex-2021.8.28-cp37-cp37m-win32.whl", hash = "sha256:4cde065ab33bcaab774d84096fae266d9301d1a2f5519d7bd58fc55274afbf7a"}, 924 | {file = "regex-2021.8.28-cp37-cp37m-win_amd64.whl", hash = "sha256:1413b5022ed6ac0d504ba425ef02549a57d0f4276de58e3ab7e82437892704fc"}, 925 | {file = "regex-2021.8.28-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:ed4b50355b066796dacdd1cf538f2ce57275d001838f9b132fab80b75e8c84dd"}, 926 | {file = "regex-2021.8.28-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:28fc475f560d8f67cc8767b94db4c9440210f6958495aeae70fac8faec631797"}, 927 | {file = "regex-2021.8.28-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:bdc178caebd0f338d57ae445ef8e9b737ddf8fbc3ea187603f65aec5b041248f"}, 928 | {file = "regex-2021.8.28-cp38-cp38-manylinux_2_5_i686.manylinux1_i686.manylinux_2_12_i686.manylinux2010_i686.whl", hash = "sha256:999ad08220467b6ad4bd3dd34e65329dd5d0df9b31e47106105e407954965256"}, 929 | {file = "regex-2021.8.28-cp38-cp38-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:808ee5834e06f57978da3e003ad9d6292de69d2bf6263662a1a8ae30788e080b"}, 930 | {file = "regex-2021.8.28-cp38-cp38-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:d5111d4c843d80202e62b4fdbb4920db1dcee4f9366d6b03294f45ed7b18b42e"}, 931 | {file = "regex-2021.8.28-cp38-cp38-win32.whl", hash = "sha256:473858730ef6d6ff7f7d5f19452184cd0caa062a20047f6d6f3e135a4648865d"}, 932 | {file = "regex-2021.8.28-cp38-cp38-win_amd64.whl", hash = "sha256:31a99a4796bf5aefc8351e98507b09e1b09115574f7c9dbb9cf2111f7220d2e2"}, 933 | {file = "regex-2021.8.28-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:04f6b9749e335bb0d2f68c707f23bb1773c3fb6ecd10edf0f04df12a8920d468"}, 934 | {file = "regex-2021.8.28-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:9b006628fe43aa69259ec04ca258d88ed19b64791693df59c422b607b6ece8bb"}, 935 | {file = "regex-2021.8.28-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:121f4b3185feaade3f85f70294aef3f777199e9b5c0c0245c774ae884b110a2d"}, 936 | {file = "regex-2021.8.28-cp39-cp39-manylinux_2_5_i686.manylinux1_i686.manylinux_2_12_i686.manylinux2010_i686.whl", hash = "sha256:a577a21de2ef8059b58f79ff76a4da81c45a75fe0bfb09bc8b7bb4293fa18983"}, 937 | {file = "regex-2021.8.28-cp39-cp39-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:1743345e30917e8c574f273f51679c294effba6ad372db1967852f12c76759d8"}, 938 | {file = "regex-2021.8.28-cp39-cp39-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:e1e8406b895aba6caa63d9fd1b6b1700d7e4825f78ccb1e5260551d168db38ed"}, 939 | {file = "regex-2021.8.28-cp39-cp39-win32.whl", hash = "sha256:ed283ab3a01d8b53de3a05bfdf4473ae24e43caee7dcb5584e86f3f3e5ab4374"}, 940 | {file = "regex-2021.8.28-cp39-cp39-win_amd64.whl", hash = "sha256:610b690b406653c84b7cb6091facb3033500ee81089867ee7d59e675f9ca2b73"}, 941 | {file = "regex-2021.8.28.tar.gz", hash = "sha256:f585cbbeecb35f35609edccb95efd95a3e35824cd7752b586503f7e6087303f1"}, 942 | ] 943 | six = [ 944 | {file = "six-1.16.0-py2.py3-none-any.whl", hash = "sha256:8abb2f1d86890a2dfb989f9a77cfcfd3e47c2a354b01111771326f8aa26e0254"}, 945 | {file = "six-1.16.0.tar.gz", hash = "sha256:1e61c37477a1626458e36f7b1d82aa5c9b094fa4802892072e49de9c60c4c926"}, 946 | ] 947 | sqlalchemy = [ 948 | {file = "SQLAlchemy-1.4.23-cp27-cp27m-macosx_10_14_x86_64.whl", hash = "sha256:25e9b2e5ca088879ce3740d9ccd4d58cb9061d49566a0b5e12166f403d6f4da0"}, 949 | {file = "SQLAlchemy-1.4.23-cp27-cp27m-manylinux_2_5_x86_64.manylinux1_x86_64.whl", hash = "sha256:d9667260125688c71ccf9af321c37e9fb71c2693575af8210f763bfbbee847c7"}, 950 | {file = "SQLAlchemy-1.4.23-cp27-cp27m-win32.whl", hash = "sha256:cec1a4c6ddf5f82191301a25504f0e675eccd86635f0d5e4c69e0661691931c5"}, 951 | {file = "SQLAlchemy-1.4.23-cp27-cp27m-win_amd64.whl", hash = "sha256:ae07895b55c7d58a7dd47438f437ac219c0f09d24c2e7d69fdebc1ea75350f00"}, 952 | {file = "SQLAlchemy-1.4.23-cp27-cp27mu-manylinux_2_5_x86_64.manylinux1_x86_64.whl", hash = "sha256:967307ea52985985224a79342527c36ec2d1daa257a39748dd90e001a4be4d90"}, 953 | {file = "SQLAlchemy-1.4.23-cp36-cp36m-macosx_10_14_x86_64.whl", hash = "sha256:be185b3daf651c6c0639987a916bf41e97b60e68f860f27c9cb6574385f5cbb4"}, 954 | {file = "SQLAlchemy-1.4.23-cp36-cp36m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:3a0d3b3d51c83a66f5b72c57e1aad061406e4c390bd42cf1fda94effe82fac81"}, 955 | {file = "SQLAlchemy-1.4.23-cp36-cp36m-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:a8395c4db3e1450eef2b68069abf500cc48af4b442a0d98b5d3c9535fe40cde8"}, 956 | {file = "SQLAlchemy-1.4.23-cp36-cp36m-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:9b128a78581faea7a5ee626ad4471353eee051e4e94616dfeff4742b6e5ba262"}, 957 | {file = "SQLAlchemy-1.4.23-cp36-cp36m-win32.whl", hash = "sha256:43fc207be06e50158e4dae4cc4f27ce80afbdbfa7c490b3b22feb64f6d9775a0"}, 958 | {file = "SQLAlchemy-1.4.23-cp36-cp36m-win_amd64.whl", hash = "sha256:e9d4f4552aa5e0d1417fc64a2ce1cdf56a30bab346ba6b0dd5e838eb56db4d29"}, 959 | {file = "SQLAlchemy-1.4.23-cp37-cp37m-macosx_10_14_x86_64.whl", hash = "sha256:512f52a8872e8d63d898e4e158eda17e2ee40b8d2496b3b409422e71016db0bd"}, 960 | {file = "SQLAlchemy-1.4.23-cp37-cp37m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:355024cf061ed04271900414eb4a22671520241d2216ddb691bdd8a992172389"}, 961 | {file = "SQLAlchemy-1.4.23-cp37-cp37m-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:82c03325111eab88d64e0ff48b6fe15c75d23787429fa1d84c0995872e702787"}, 962 | {file = "SQLAlchemy-1.4.23-cp37-cp37m-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:0aa312f9906ecebe133d7f44168c3cae4c76f27a25192fa7682f3fad505543c9"}, 963 | {file = "SQLAlchemy-1.4.23-cp37-cp37m-win32.whl", hash = "sha256:059c5f41e8630f51741a234e6ba2a034228c11b3b54a15478e61d8b55fa8bd9d"}, 964 | {file = "SQLAlchemy-1.4.23-cp37-cp37m-win_amd64.whl", hash = "sha256:cd68c5f9d13ffc8f4d6802cceee786678c5b1c668c97bc07b9f4a60883f36cd1"}, 965 | {file = "SQLAlchemy-1.4.23-cp38-cp38-macosx_10_14_x86_64.whl", hash = "sha256:6a8dbf3d46e889d864a57ee880c4ad3a928db5aa95e3d359cbe0da2f122e50c4"}, 966 | {file = "SQLAlchemy-1.4.23-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:1c15191f2430a30082f540ec6f331214746fc974cfdf136d7a1471d1c61d68ff"}, 967 | {file = "SQLAlchemy-1.4.23-cp38-cp38-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:cd0e85dd2067159848c7672acd517f0c38b7b98867a347411ea01b432003f8d9"}, 968 | {file = "SQLAlchemy-1.4.23-cp38-cp38-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:370f4688ce47f0dc1e677a020a4d46252a31a2818fd67f5c256417faefc938af"}, 969 | {file = "SQLAlchemy-1.4.23-cp38-cp38-win32.whl", hash = "sha256:bd41f8063a9cd11b76d6d7d6af8139ab3c087f5dbbe5a50c02cb8ece7da34d67"}, 970 | {file = "SQLAlchemy-1.4.23-cp38-cp38-win_amd64.whl", hash = "sha256:2bca9a6e30ee425cc321d988a152a5fe1be519648e7541ac45c36cd4f569421f"}, 971 | {file = "SQLAlchemy-1.4.23-cp39-cp39-macosx_10_14_x86_64.whl", hash = "sha256:4803a481d4c14ce6ad53dc35458c57821863e9a079695c27603d38355e61fb7f"}, 972 | {file = "SQLAlchemy-1.4.23-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:07b9099a95dd2b2620498544300eda590741ac54915c6b20809b6de7e3c58090"}, 973 | {file = "SQLAlchemy-1.4.23-cp39-cp39-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:37f2bd1b8e32c5999280f846701712347fc0ee7370e016ede2283c71712e127a"}, 974 | {file = "SQLAlchemy-1.4.23-cp39-cp39-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:448612570aa1437a5d1b94ada161805778fe80aba5b9a08a403e8ae4e071ded6"}, 975 | {file = "SQLAlchemy-1.4.23-cp39-cp39-win32.whl", hash = "sha256:e0ce4a2e48fe0a9ea3a5160411a4c5135da5255ed9ac9c15f15f2bcf58c34194"}, 976 | {file = "SQLAlchemy-1.4.23-cp39-cp39-win_amd64.whl", hash = "sha256:0aa746d1173587743960ff17b89b540e313aacfe6c1e9c81aa48393182c36d4f"}, 977 | {file = "SQLAlchemy-1.4.23.tar.gz", hash = "sha256:76ff246881f528089bf19385131b966197bb494653990396d2ce138e2a447583"}, 978 | ] 979 | sqlalchemy2-stubs = [ 980 | {file = "sqlalchemy2-stubs-0.0.2a15.tar.gz", hash = "sha256:9336e0724c985623e055e2db28e8d78a62b40a2628b862c6cd50d7942fd5a238"}, 981 | {file = "sqlalchemy2_stubs-0.0.2a15-py3-none-any.whl", hash = "sha256:3da19252c87c1ae6bf0e49c2873e72a6e5684a1ede2490c8b75b78834239258b"}, 982 | ] 983 | starlette = [ 984 | {file = "starlette-0.14.2-py3-none-any.whl", hash = "sha256:3c8e48e52736b3161e34c9f0e8153b4f32ec5d8995a3ee1d59410d92f75162ed"}, 985 | {file = "starlette-0.14.2.tar.gz", hash = "sha256:7d49f4a27f8742262ef1470608c59ddbc66baf37c148e938c7038e6bc7a998aa"}, 986 | ] 987 | strawberry-graphql = [ 988 | {file = "strawberry-graphql-0.77.10.tar.gz", hash = "sha256:e55d3f20485faab8e9e50d28376b52bbbaefe1ce6b628cc1c7bff40afdad37b6"}, 989 | {file = "strawberry_graphql-0.77.10-py3-none-any.whl", hash = "sha256:e0bbd0832d310c52d6f10425eb790db3a667baaf251959bbdfb4860209c37ce7"}, 990 | ] 991 | toml = [ 992 | {file = "toml-0.10.2-py2.py3-none-any.whl", hash = "sha256:806143ae5bfb6a3c6e736a764057db0e6a0e05e338b5630894a5f779cabb4f9b"}, 993 | {file = "toml-0.10.2.tar.gz", hash = "sha256:b3bda1d108d5dd99f4a20d24d9c348e91c4db7ab1b749200bded2f839ccbe68f"}, 994 | ] 995 | tomli = [ 996 | {file = "tomli-1.2.1-py3-none-any.whl", hash = "sha256:8dd0e9524d6f386271a36b41dbf6c57d8e32fd96fd22b6584679dc569d20899f"}, 997 | {file = "tomli-1.2.1.tar.gz", hash = "sha256:a5b75cb6f3968abb47af1b40c1819dc519ea82bcc065776a866e8d74c5ca9442"}, 998 | ] 999 | typed-ast = [ 1000 | {file = "typed_ast-1.4.3-cp35-cp35m-manylinux1_i686.whl", hash = "sha256:2068531575a125b87a41802130fa7e29f26c09a2833fea68d9a40cf33902eba6"}, 1001 | {file = "typed_ast-1.4.3-cp35-cp35m-manylinux1_x86_64.whl", hash = "sha256:c907f561b1e83e93fad565bac5ba9c22d96a54e7ea0267c708bffe863cbe4075"}, 1002 | {file = "typed_ast-1.4.3-cp35-cp35m-manylinux2014_aarch64.whl", hash = "sha256:1b3ead4a96c9101bef08f9f7d1217c096f31667617b58de957f690c92378b528"}, 1003 | {file = "typed_ast-1.4.3-cp35-cp35m-win32.whl", hash = "sha256:dde816ca9dac1d9c01dd504ea5967821606f02e510438120091b84e852367428"}, 1004 | {file = "typed_ast-1.4.3-cp35-cp35m-win_amd64.whl", hash = "sha256:777a26c84bea6cd934422ac2e3b78863a37017618b6e5c08f92ef69853e765d3"}, 1005 | {file = "typed_ast-1.4.3-cp36-cp36m-macosx_10_9_x86_64.whl", hash = "sha256:f8afcf15cc511ada719a88e013cec87c11aff7b91f019295eb4530f96fe5ef2f"}, 1006 | {file = "typed_ast-1.4.3-cp36-cp36m-manylinux1_i686.whl", hash = "sha256:52b1eb8c83f178ab787f3a4283f68258525f8d70f778a2f6dd54d3b5e5fb4341"}, 1007 | {file = "typed_ast-1.4.3-cp36-cp36m-manylinux1_x86_64.whl", hash = "sha256:01ae5f73431d21eead5015997ab41afa53aa1fbe252f9da060be5dad2c730ace"}, 1008 | {file = "typed_ast-1.4.3-cp36-cp36m-manylinux2014_aarch64.whl", hash = "sha256:c190f0899e9f9f8b6b7863debfb739abcb21a5c054f911ca3596d12b8a4c4c7f"}, 1009 | {file = "typed_ast-1.4.3-cp36-cp36m-win32.whl", hash = "sha256:398e44cd480f4d2b7ee8d98385ca104e35c81525dd98c519acff1b79bdaac363"}, 1010 | {file = "typed_ast-1.4.3-cp36-cp36m-win_amd64.whl", hash = "sha256:bff6ad71c81b3bba8fa35f0f1921fb24ff4476235a6e94a26ada2e54370e6da7"}, 1011 | {file = "typed_ast-1.4.3-cp37-cp37m-macosx_10_9_x86_64.whl", hash = "sha256:0fb71b8c643187d7492c1f8352f2c15b4c4af3f6338f21681d3681b3dc31a266"}, 1012 | {file = "typed_ast-1.4.3-cp37-cp37m-manylinux1_i686.whl", hash = "sha256:760ad187b1041a154f0e4d0f6aae3e40fdb51d6de16e5c99aedadd9246450e9e"}, 1013 | {file = "typed_ast-1.4.3-cp37-cp37m-manylinux1_x86_64.whl", hash = "sha256:5feca99c17af94057417d744607b82dd0a664fd5e4ca98061480fd8b14b18d04"}, 1014 | {file = "typed_ast-1.4.3-cp37-cp37m-manylinux2014_aarch64.whl", hash = "sha256:95431a26309a21874005845c21118c83991c63ea800dd44843e42a916aec5899"}, 1015 | {file = "typed_ast-1.4.3-cp37-cp37m-win32.whl", hash = "sha256:aee0c1256be6c07bd3e1263ff920c325b59849dc95392a05f258bb9b259cf39c"}, 1016 | {file = "typed_ast-1.4.3-cp37-cp37m-win_amd64.whl", hash = "sha256:9ad2c92ec681e02baf81fdfa056fe0d818645efa9af1f1cd5fd6f1bd2bdfd805"}, 1017 | {file = "typed_ast-1.4.3-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:b36b4f3920103a25e1d5d024d155c504080959582b928e91cb608a65c3a49e1a"}, 1018 | {file = "typed_ast-1.4.3-cp38-cp38-manylinux1_i686.whl", hash = "sha256:067a74454df670dcaa4e59349a2e5c81e567d8d65458d480a5b3dfecec08c5ff"}, 1019 | {file = "typed_ast-1.4.3-cp38-cp38-manylinux1_x86_64.whl", hash = "sha256:7538e495704e2ccda9b234b82423a4038f324f3a10c43bc088a1636180f11a41"}, 1020 | {file = "typed_ast-1.4.3-cp38-cp38-manylinux2014_aarch64.whl", hash = "sha256:af3d4a73793725138d6b334d9d247ce7e5f084d96284ed23f22ee626a7b88e39"}, 1021 | {file = "typed_ast-1.4.3-cp38-cp38-win32.whl", hash = "sha256:f2362f3cb0f3172c42938946dbc5b7843c2a28aec307c49100c8b38764eb6927"}, 1022 | {file = "typed_ast-1.4.3-cp38-cp38-win_amd64.whl", hash = "sha256:dd4a21253f42b8d2b48410cb31fe501d32f8b9fbeb1f55063ad102fe9c425e40"}, 1023 | {file = "typed_ast-1.4.3-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:f328adcfebed9f11301eaedfa48e15bdece9b519fb27e6a8c01aa52a17ec31b3"}, 1024 | {file = "typed_ast-1.4.3-cp39-cp39-manylinux1_i686.whl", hash = "sha256:2c726c276d09fc5c414693a2de063f521052d9ea7c240ce553316f70656c84d4"}, 1025 | {file = "typed_ast-1.4.3-cp39-cp39-manylinux1_x86_64.whl", hash = "sha256:cae53c389825d3b46fb37538441f75d6aecc4174f615d048321b716df2757fb0"}, 1026 | {file = "typed_ast-1.4.3-cp39-cp39-manylinux2014_aarch64.whl", hash = "sha256:b9574c6f03f685070d859e75c7f9eeca02d6933273b5e69572e5ff9d5e3931c3"}, 1027 | {file = "typed_ast-1.4.3-cp39-cp39-win32.whl", hash = "sha256:209596a4ec71d990d71d5e0d312ac935d86930e6eecff6ccc7007fe54d703808"}, 1028 | {file = "typed_ast-1.4.3-cp39-cp39-win_amd64.whl", hash = "sha256:9c6d1a54552b5330bc657b7ef0eae25d00ba7ffe85d9ea8ae6540d2197a3788c"}, 1029 | {file = "typed_ast-1.4.3.tar.gz", hash = "sha256:fb1bbeac803adea29cedd70781399c99138358c26d05fcbd23c13016b7f5ec65"}, 1030 | ] 1031 | typing-extensions = [ 1032 | {file = "typing_extensions-3.10.0.2-py2-none-any.whl", hash = "sha256:d8226d10bc02a29bcc81df19a26e56a9647f8b0a6d4a83924139f4a8b01f17b7"}, 1033 | {file = "typing_extensions-3.10.0.2-py3-none-any.whl", hash = "sha256:f1d25edafde516b146ecd0613dabcc61409817af4766fbbcfb8d1ad4ec441a34"}, 1034 | {file = "typing_extensions-3.10.0.2.tar.gz", hash = "sha256:49f75d16ff11f1cd258e1b988ccff82a3ca5570217d7ad8c5f48205dd99a677e"}, 1035 | ] 1036 | uvicorn = [ 1037 | {file = "uvicorn-0.15.0-py3-none-any.whl", hash = "sha256:17f898c64c71a2640514d4089da2689e5db1ce5d4086c2d53699bf99513421c1"}, 1038 | {file = "uvicorn-0.15.0.tar.gz", hash = "sha256:d9a3c0dd1ca86728d3e235182683b4cf94cd53a867c288eaeca80ee781b2caff"}, 1039 | ] 1040 | uvloop = [ 1041 | {file = "uvloop-0.16.0-cp310-cp310-macosx_10_9_universal2.whl", hash = "sha256:6224f1401025b748ffecb7a6e2652b17768f30b1a6a3f7b44660e5b5b690b12d"}, 1042 | {file = "uvloop-0.16.0-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:30ba9dcbd0965f5c812b7c2112a1ddf60cf904c1c160f398e7eed3a6b82dcd9c"}, 1043 | {file = "uvloop-0.16.0-cp310-cp310-manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:bd53f7f5db562f37cd64a3af5012df8cac2c464c97e732ed556800129505bd64"}, 1044 | {file = "uvloop-0.16.0-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:772206116b9b57cd625c8a88f2413df2fcfd0b496eb188b82a43bed7af2c2ec9"}, 1045 | {file = "uvloop-0.16.0-cp37-cp37m-macosx_10_9_x86_64.whl", hash = "sha256:b572256409f194521a9895aef274cea88731d14732343da3ecdb175228881638"}, 1046 | {file = "uvloop-0.16.0-cp37-cp37m-manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:04ff57aa137230d8cc968f03481176041ae789308b4d5079118331ab01112450"}, 1047 | {file = "uvloop-0.16.0-cp37-cp37m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:3a19828c4f15687675ea912cc28bbcb48e9bb907c801873bd1519b96b04fb805"}, 1048 | {file = "uvloop-0.16.0-cp38-cp38-macosx_10_9_universal2.whl", hash = "sha256:e814ac2c6f9daf4c36eb8e85266859f42174a4ff0d71b99405ed559257750382"}, 1049 | {file = "uvloop-0.16.0-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:bd8f42ea1ea8f4e84d265769089964ddda95eb2bb38b5cbe26712b0616c3edee"}, 1050 | {file = "uvloop-0.16.0-cp38-cp38-manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:647e481940379eebd314c00440314c81ea547aa636056f554d491e40503c8464"}, 1051 | {file = "uvloop-0.16.0-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:8e0d26fa5875d43ddbb0d9d79a447d2ace4180d9e3239788208527c4784f7cab"}, 1052 | {file = "uvloop-0.16.0-cp39-cp39-macosx_10_9_universal2.whl", hash = "sha256:6ccd57ae8db17d677e9e06192e9c9ec4bd2066b77790f9aa7dede2cc4008ee8f"}, 1053 | {file = "uvloop-0.16.0-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:089b4834fd299d82d83a25e3335372f12117a7d38525217c2258e9b9f4578897"}, 1054 | {file = "uvloop-0.16.0-cp39-cp39-manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:98d117332cc9e5ea8dfdc2b28b0a23f60370d02e1395f88f40d1effd2cb86c4f"}, 1055 | {file = "uvloop-0.16.0-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:1e5f2e2ff51aefe6c19ee98af12b4ae61f5be456cd24396953244a30880ad861"}, 1056 | {file = "uvloop-0.16.0.tar.gz", hash = "sha256:f74bc20c7b67d1c27c72601c78cf95be99d5c2cdd4514502b4f3eb0933ff1228"}, 1057 | ] 1058 | watchgod = [ 1059 | {file = "watchgod-0.7-py3-none-any.whl", hash = "sha256:d6c1ea21df37847ac0537ca0d6c2f4cdf513562e95f77bb93abbcf05573407b7"}, 1060 | {file = "watchgod-0.7.tar.gz", hash = "sha256:48140d62b0ebe9dd9cf8381337f06351e1f2e70b2203fa9c6eff4e572ca84f29"}, 1061 | ] 1062 | websockets = [ 1063 | {file = "websockets-10.0-cp37-cp37m-macosx_10_9_x86_64.whl", hash = "sha256:cd8c6f2ec24aedace251017bc7a414525171d4e6578f914acab9349362def4da"}, 1064 | {file = "websockets-10.0-cp37-cp37m-manylinux1_i686.whl", hash = "sha256:1f6b814cff6aadc4288297cb3a248614829c6e4ff5556593c44a115e9dd49939"}, 1065 | {file = "websockets-10.0-cp37-cp37m-manylinux1_x86_64.whl", hash = "sha256:01db0ecd1a0ca6702d02a5ed40413e18b7d22f94afb3bbe0d323bac86c42c1c8"}, 1066 | {file = "websockets-10.0-cp37-cp37m-manylinux2010_i686.whl", hash = "sha256:82b17524b1ce6ae7f7dd93e4d18e9b9474071e28b65dbf1dfe9b5767778db379"}, 1067 | {file = "websockets-10.0-cp37-cp37m-manylinux2010_x86_64.whl", hash = "sha256:8bbf8660c3f833ddc8b1afab90213f2e672a9ddac6eecb3cde968e6b2807c1c7"}, 1068 | {file = "websockets-10.0-cp37-cp37m-manylinux2014_aarch64.whl", hash = "sha256:b8176deb6be540a46695960a765a77c28ac8b2e3ef2ec95d50a4f5df901edb1c"}, 1069 | {file = "websockets-10.0-cp37-cp37m-win32.whl", hash = "sha256:706e200fc7f03bed99ad0574cd1ea8b0951477dd18cc978ccb190683c69dba76"}, 1070 | {file = "websockets-10.0-cp37-cp37m-win_amd64.whl", hash = "sha256:5b2600e01c7ca6f840c42c747ffbe0254f319594ed108db847eb3d75f4aacb80"}, 1071 | {file = "websockets-10.0-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:085bb8a6e780d30eaa1ba48ac7f3a6707f925edea787cfb761ce5a39e77ac09b"}, 1072 | {file = "websockets-10.0-cp38-cp38-manylinux1_i686.whl", hash = "sha256:9a4d889162bd48588e80950e07fa5e039eee9deb76a58092e8c3ece96d7ef537"}, 1073 | {file = "websockets-10.0-cp38-cp38-manylinux1_x86_64.whl", hash = "sha256:b4ade7569b6fd17912452f9c3757d96f8e4044016b6d22b3b8391e641ca50456"}, 1074 | {file = "websockets-10.0-cp38-cp38-manylinux2010_i686.whl", hash = "sha256:2a43072e434c041a99f2e1eb9b692df0232a38c37c61d00e9f24db79474329e4"}, 1075 | {file = "websockets-10.0-cp38-cp38-manylinux2010_x86_64.whl", hash = "sha256:7f79f02c7f9a8320aff7d3321cd1c7e3a7dbc15d922ac996cca827301ee75238"}, 1076 | {file = "websockets-10.0-cp38-cp38-manylinux2014_aarch64.whl", hash = "sha256:1ac35426fe3e7d3d0fac3d63c8965c76ed67a8fd713937be072bf0ce22808539"}, 1077 | {file = "websockets-10.0-cp38-cp38-win32.whl", hash = "sha256:ff59c6bdb87b31f7e2d596f09353d5a38c8c8ff571b0e2238e8ee2d55ad68465"}, 1078 | {file = "websockets-10.0-cp38-cp38-win_amd64.whl", hash = "sha256:d67646ddd17a86117ae21c27005d83c1895c0cef5d7be548b7549646372f868a"}, 1079 | {file = "websockets-10.0-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:82bd921885231f4a30d9bc550552495b3fc36b1235add6d374e7c65c3babd805"}, 1080 | {file = "websockets-10.0-cp39-cp39-manylinux1_i686.whl", hash = "sha256:7d2e12e4f901f1bc062dfdf91831712c4106ed18a9a4cdb65e2e5f502124ca37"}, 1081 | {file = "websockets-10.0-cp39-cp39-manylinux1_x86_64.whl", hash = "sha256:71358c7816e2762f3e4af3adf0040f268e219f5a38cb3487a9d0fc2e554fef6a"}, 1082 | {file = "websockets-10.0-cp39-cp39-manylinux2010_i686.whl", hash = "sha256:fe83b3ec9ef34063d86dfe1029160a85f24a5a94271036e5714a57acfdd089a1"}, 1083 | {file = "websockets-10.0-cp39-cp39-manylinux2010_x86_64.whl", hash = "sha256:eb282127e9c136f860c6068a4fba5756eb25e755baffb5940b6f1eae071928b2"}, 1084 | {file = "websockets-10.0-cp39-cp39-manylinux2014_aarch64.whl", hash = "sha256:62160772314920397f9d219147f958b33fa27a12c662d4455c9ccbba9a07e474"}, 1085 | {file = "websockets-10.0-cp39-cp39-win32.whl", hash = "sha256:e42a1f1e03437b017af341e9bbfdc09252cd48ef32a8c3c3ead769eab3b17368"}, 1086 | {file = "websockets-10.0-cp39-cp39-win_amd64.whl", hash = "sha256:c5880442f5fc268f1ef6d37b2c152c114deccca73f48e3a8c48004d2f16f4567"}, 1087 | {file = "websockets-10.0.tar.gz", hash = "sha256:c4fc9a1d242317892590abe5b61a9127f1a61740477bfb121743f290b8054002"}, 1088 | ] 1089 | zipp = [ 1090 | {file = "zipp-3.5.0-py3-none-any.whl", hash = "sha256:957cfda87797e389580cb8b9e3870841ca991e2125350677b2ca83a0e99390a3"}, 1091 | {file = "zipp-3.5.0.tar.gz", hash = "sha256:f5812b1e007e48cff63449a5e9f4e7ebea716b4111f9c4f9a645f91d579bf0c4"}, 1092 | ] 1093 | -------------------------------------------------------------------------------- /fastapi-sqlalchemy/pyproject.toml: -------------------------------------------------------------------------------- 1 | [tool.poetry] 2 | name = "starlette-sqlalchemy" 3 | version = "0.1.0" 4 | description = "" 5 | authors = ["Jonathan Kim "] 6 | 7 | [tool.poetry.dependencies] 8 | python = "^3.7" 9 | uvicorn = {extras = ["standard"], version = "^0.15.0"} 10 | SQLAlchemy = {extras = ["mypy"], version = "^1.4.23"} 11 | alembic = "^1.7.1" 12 | strawberry-graphql = {extras = ["asgi"], version = "^0.77.0"} 13 | fastapi = "^0.68.1" 14 | 15 | 16 | [tool.poetry.dev-dependencies] 17 | black = "^21.8b0" 18 | flake8 = "^3.9.2" 19 | flake8-black = "^0.2.3" 20 | flake8-bugbear = "^21.4.3" 21 | mypy = "^0.910" 22 | 23 | [build-system] 24 | requires = ["poetry-core>=1.0.0"] 25 | build-backend = "poetry.core.masonry.api" 26 | -------------------------------------------------------------------------------- /fastapi-sqlalchemy/setup.cfg: -------------------------------------------------------------------------------- 1 | [mypy] 2 | plugins = sqlalchemy.ext.mypy.plugin,strawberry.ext.mypy_plugin 3 | -------------------------------------------------------------------------------- /fastapi/.projectroot: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/strawberry-graphql/examples/8a1cddbc41d3e7dfdcf2a6e1192b2bb730e3b7a1/fastapi/.projectroot -------------------------------------------------------------------------------- /fastapi/README.md: -------------------------------------------------------------------------------- 1 | # Example of a GraphQL API using Strawberry and FastAPI 2 | 3 | This examples shows you how to setup Strawberry with FastAPI 4 | 5 | ## How to use 6 | 7 | 1. Install dependencies 8 | 9 | Use [poetry](https://python-poetry.org/) to install dependencies: 10 | 11 | ```bash 12 | poetry install 13 | ``` 14 | 15 | 2. Run the server 16 | 17 | Run [uvicorn](https://www.uvicorn.org/) to run the server: 18 | 19 | ```bash 20 | poetry run uvicorn main:app --reload 21 | ``` 22 | 23 | 3. Access the GraphiQL IDE and explore the schema at [http://localhost:8000/graphql](http://localhost:8000/graphql) 24 | 25 | ## Example query 26 | 27 | ```graphql 28 | query AllTopRatedMovies { 29 | topRatedMovies { 30 | imageUrl 31 | imdbId 32 | imdbRating 33 | imdbRatingCount 34 | title 35 | year 36 | } 37 | } 38 | ``` 39 | -------------------------------------------------------------------------------- /fastapi/api/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/strawberry-graphql/examples/8a1cddbc41d3e7dfdcf2a6e1192b2bb730e3b7a1/fastapi/api/__init__.py -------------------------------------------------------------------------------- /fastapi/api/definitions/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/strawberry-graphql/examples/8a1cddbc41d3e7dfdcf2a6e1192b2bb730e3b7a1/fastapi/api/definitions/__init__.py -------------------------------------------------------------------------------- /fastapi/api/definitions/movie.py: -------------------------------------------------------------------------------- 1 | import strawberry 2 | 3 | 4 | @strawberry.type 5 | class Movie: 6 | imdb_id: str = strawberry.field(description="This is the IMDB ID of the movie") 7 | title: str 8 | year: int 9 | image_url: str 10 | imdb_rating: float 11 | imdb_rating_count: str 12 | -------------------------------------------------------------------------------- /fastapi/api/schema.py: -------------------------------------------------------------------------------- 1 | from typing import List 2 | 3 | import json 4 | import strawberry 5 | 6 | from .definitions.movie import Movie 7 | 8 | 9 | @strawberry.type 10 | class Query: 11 | @strawberry.field 12 | def top_rated_movies(self, info, limit: int = 250) -> List[Movie]: 13 | with open("../common-data/movies.json", "r") as file: 14 | data = json.load(file) 15 | 16 | result = [] 17 | 18 | for i in range(limit): 19 | result.append( 20 | Movie( 21 | imdb_id=data[i]["imdb_id"], 22 | title=data[i]["title"], 23 | year=data[i]["year"], 24 | image_url=data[i]["image_url"], 25 | imdb_rating=data[i]["imdb_rating"], 26 | imdb_rating_count=data[i]["imdb_rating_count"], 27 | ) 28 | ) 29 | 30 | return result 31 | 32 | 33 | schema = strawberry.Schema(Query) 34 | -------------------------------------------------------------------------------- /fastapi/main/__init__.py: -------------------------------------------------------------------------------- 1 | from fastapi import FastAPI, Request 2 | from fastapi.templating import Jinja2Templates 3 | from fastapi.responses import HTMLResponse 4 | from strawberry.asgi import GraphQL 5 | 6 | from api.schema import schema 7 | 8 | app = FastAPI() 9 | 10 | templates = Jinja2Templates(directory="templates") 11 | 12 | 13 | @app.get("/", response_class=HTMLResponse) 14 | async def render_index_page(request: Request): 15 | return templates.TemplateResponse("index.html", {"request": request}) 16 | 17 | 18 | app.mount("/graphql", GraphQL(schema)) 19 | -------------------------------------------------------------------------------- /fastapi/pyproject.toml: -------------------------------------------------------------------------------- 1 | [tool.poetry] 2 | name = "strawberry-graphql-fastapi-example" 3 | version = "0.1.0" 4 | description = "Example of a GraphQL API using Strawberry and FastAPI" 5 | authors = ["Rodrigo Feijao "] 6 | 7 | [tool.poetry.dependencies] 8 | python = "^3.11" 9 | uvicorn = {extras = ["standard"], version = "^0.24.0"} 10 | strawberry-graphql = {extras = ["asgi"], version = "^0.214.0"} 11 | fastapi = "^0.104.1" 12 | 13 | 14 | [tool.poetry.dev-dependencies] 15 | black = "^23.11" 16 | mypy = "^1.7.0" 17 | ruff = "^0.0.47" 18 | 19 | [build-system] 20 | requires = ["poetry-core>=1.8.0"] 21 | build-backend = "poetry.core.masonry.api" 22 | 23 | [tool.ruff] 24 | line-length = 88 25 | select = [ 26 | "F401", 27 | "F403", 28 | "E501", 29 | ] 30 | -------------------------------------------------------------------------------- /fastapi/setup.cfg: -------------------------------------------------------------------------------- 1 | [mypy] 2 | plugins = strawberry.ext.mypy_plugin 3 | -------------------------------------------------------------------------------- /fastapi/templates/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | Example of a GraphQL API using Strawberry and FastAPI 4 | 5 | 6 | Strawberry GraphQL 7 | 8 | 9 | --------------------------------------------------------------------------------