diff --git a/.github/workflows/docs.yml b/.github/workflows/docs.yml new file mode 100644 index 0000000..2e2a45b --- /dev/null +++ b/.github/workflows/docs.yml @@ -0,0 +1,30 @@ +name: Coral AIOHTTP - Docs + +on: + push: + branches: + - main + +jobs: + build_and_push: + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v3 + - name: Set up Python + uses: actions/setup-python@v4 + with: + python-version: "3.9" + - name: Set up Poetry + uses: abatilo/actions-poetry@v2.0.0 + with: + poetry-version: 1.1.13 + - name: Install dependencies + run: poetry install + - name: Build And Commit Site + run: | + poetry run mkdocs build + git config user.name github-actions + git config user.email github-actions@github.com + git add site + git commit -m "ci: build and commit documentation" + git push diff --git a/.github/workflows/publish.yml b/.github/workflows/publish.yml new file mode 100644 index 0000000..4121900 --- /dev/null +++ b/.github/workflows/publish.yml @@ -0,0 +1,23 @@ +name: Coral AIOHTTP - Publish + +on: + release: + types: [published] + +jobs: + build_and_publish: + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v3 + - name: Set up Python + uses: actions/setup-python@v4 + with: + python-version: "3.9" + - name: Set up Poetry + uses: abatilo/actions-poetry@v2.0.0 + with: + poetry-version: 1.1.13 + - name: Install dependencies + run: poetry install + - name: Publish + run: poetry publish --build --username "${{secrets.PYPI_USERNAME}}" --password "${{secrets.PYPI_PASSWORD}}" --no-interaction \ No newline at end of file diff --git a/.github/workflows/pytest.yml b/.github/workflows/pytest.yml new file mode 100644 index 0000000..e7d51a9 --- /dev/null +++ b/.github/workflows/pytest.yml @@ -0,0 +1,30 @@ +name: Coral AIOHTTP - Pytest + +on: [push] + +jobs: + test: + + strategy: + fail-fast: false + matrix: + python-version: ["3.7", "3.8", "3.9", "3.10"] + poetry-version: ["1.1.13"] + os: [ubuntu-latest, macos-latest, windows-latest] + + runs-on: ${{ matrix.os }} + + steps: + - uses: actions/checkout@v3 + - name: Set up Python ${{ matrix.python-version }} + uses: actions/setup-python@v4 + with: + python-version: ${{ matrix.python-version }} + - name: Set up Poetry ${{ matrix.poetry-version }} + uses: abatilo/actions-poetry@v2.0.0 + with: + poetry-version: ${{ matrix.poetry-version }} + - name: Install dependencies + run: poetry install + - name: Run Pytest + run: poetry run pytest --cov=src --cov-report=xml \ No newline at end of file diff --git a/.gitignore b/.gitignore index b4503e9..2e30291 100644 --- a/.gitignore +++ b/.gitignore @@ -76,9 +76,6 @@ ENV/ env.bak/ venv.bak/ -# mkdocs documentation -/site - .idea/ # install stamp diff --git a/.nojekyll b/.nojekyll new file mode 100644 index 0000000..e69de29 diff --git a/LICENSE b/LICENSE new file mode 100644 index 0000000..72a42a1 --- /dev/null +++ b/LICENSE @@ -0,0 +1,21 @@ +MIT License + +Copyright (c) 2021 Daniel Seifert + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. \ No newline at end of file diff --git a/README.md b/README.md index e69de29..642b068 100644 --- a/README.md +++ b/README.md @@ -0,0 +1,65 @@ +# Qlient AIOHTTP: Python GraphQL Client + +[](https://deepsource.io/gh/qlient-org/python-qlient-aiohttp/?ref=repository-badge) +[](https://deepsource.io/gh/qlient-org/python-qlient-aiohttp/?ref=repository-badge) +[](https://pypi.python.org/pypi/qlient-aiohttp) +[](https://github.com/qlient-org/python-qlient-aiohttp) +[](https://github.com/qlient-org/python-qlient-aiohttp/blob/master/LICENSE) + +A blazingly fast and modern graphql client based on qlient-core and aiohttp + +## Key Features + +* Compatible with Python 3.7 and above +* Build on top of ``qlient-core`` and ``aiohttp`` +* support for subscriptions + +## Help + +See the [documentation](https://qlient-org.github.io/python-qlient-aiohttp/site/) for more details. + +## Quick Preview + +_This preview is using the official [github/graphql/swapi-graphql]() graphql api._ + +```python +import asyncio + +from qlient.aiohttp import AIOHTTPClient, GraphQLResponse + + +async def main(): + async with AIOHTTPClient("https://swapi-graphql.netlify.app/.netlify/functions/index") as client: + result: GraphQLResponse = await client.query.film( + ["title", "id"], # fields selection + id="ZmlsbXM6MQ==" # query arguments + ) + + print(result.request.query) + print(result.data) + + +asyncio.run(main()) +``` + +Which results in the following query being sent to the server + +```graphql +query film($id: ID) { + film(id: $id) { + title + id + } +} +``` + +And returns the body below + +```json +{ + "film": { + "title": "A New Hope", + "id": "ZmlsbXM6MQ==" + } +} +``` \ No newline at end of file diff --git a/docs/api.md b/docs/api.md new file mode 100644 index 0000000..c439447 --- /dev/null +++ b/docs/api.md @@ -0,0 +1,9 @@ +# API + +## Clients + +::: qlient.aiohttp.clients + +## Backends + +::: qlient.aiohttp.backends \ No newline at end of file diff --git a/docs/index.md b/docs/index.md index e69de29..90b84ad 100644 --- a/docs/index.md +++ b/docs/index.md @@ -0,0 +1,60 @@ +# Introduction + +[](https://deepsource.io/gh/qlient-org/python-qlient-aiohttp/?ref=repository-badge) +[](https://deepsource.io/gh/qlient-org/python-qlient-aiohttp/?ref=repository-badge) +[](https://pypi.python.org/pypi/qlient-aiohttp) +[](https://github.com/qlient-org/python-qlient-aiohttp) +[](https://github.com/qlient-org/python-qlient-aiohttp/blob/master/LICENSE) + +A blazingly fast and modern graphql client based on qlient-core and aiohttp + +## Key Features + +* Compatible with Python 3.7 and above +* Build on top of ``qlient-core`` and ``aiohttp`` + +## Quick Preview + +_This preview is using the official [github/graphql/swapi-graphql]() graphql api._ + +```python +import asyncio + +from qlient.aiohttp import AIOHTTPClient, GraphQLResponse + + +async def main(): + async with AIOHTTPClient("https://swapi-graphql.netlify.app/.netlify/functions/index") as client: + result: GraphQLResponse = await client.query.film( + ["title", "id"], # fields selection + id="ZmlsbXM6MQ==" # query arguments + ) + + print(result.request.query) + print(result.data) + + +asyncio.run(main()) +``` + +Which results in the following query being sent to the server + +```graphql +query film($id: ID) { + film(id: $id) { + title + id + } +} +``` + +And returns the body below + +```json +{ + "film": { + "title": "A New Hope", + "id": "ZmlsbXM6MQ==" + } +} +``` \ No newline at end of file diff --git a/index.html b/index.html new file mode 100644 index 0000000..fff31e5 --- /dev/null +++ b/index.html @@ -0,0 +1,16 @@ + + +
+ +The client implementation for aiohttp
+ + + +AIOHTTPClient
+
+
+
+ Bases: AsyncClient
The aiohttp implementation for qlient.
+ +Examples:
+Basic Example
+>>> async with AIOHTTPClient("https://...") as client:
+>>> result = await client.query.get_books(...)
+With custom client session
+>>> import aiohttp
+>>> async with aiohttp.ClientSession() as session:
+>>> async with AIOHTTPClient(AIOHTTPBackend("https://...", session=session)) as client:
+>>> result = await client.query.get_books(...)
+qlient/aiohttp/clients.py9 +10 +11 +12 +13 +14 +15 +16 +17 +18 +19 +20 +21 +22 +23 +24 +25 +26 +27 +28 +29 +30 +31 +32 | |
AIOHTTPBackend
+
+
+
+ Bases: AsyncBackend
qlient/aiohttp/backends.py33 + 34 + 35 + 36 + 37 + 38 + 39 + 40 + 41 + 42 + 43 + 44 + 45 + 46 + 47 + 48 + 49 + 50 + 51 + 52 + 53 + 54 + 55 + 56 + 57 + 58 + 59 + 60 + 61 + 62 + 63 + 64 + 65 + 66 + 67 + 68 + 69 + 70 + 71 + 72 + 73 + 74 + 75 + 76 + 77 + 78 + 79 + 80 + 81 + 82 + 83 + 84 + 85 + 86 + 87 + 88 + 89 + 90 + 91 + 92 + 93 + 94 + 95 + 96 + 97 + 98 + 99 +100 +101 +102 +103 +104 +105 +106 +107 +108 +109 +110 +111 +112 +113 +114 +115 +116 +117 +118 +119 +120 +121 +122 +123 +124 +125 +126 +127 +128 +129 +130 +131 +132 +133 +134 +135 +136 +137 +138 +139 +140 +141 +142 +143 +144 +145 +146 +147 +148 +149 +150 +151 +152 +153 +154 +155 +156 +157 +158 +159 +160 +161 +162 +163 +164 +165 +166 +167 +168 +169 +170 +171 +172 +173 +174 +175 +176 +177 +178 +179 +180 +181 +182 +183 +184 | |
adapt_to_websocket_endpoint(endpoint)
+
+
+ staticmethod
+
+
+Adapt the http endpoint to websocket endpoint
+ +Parameters:
+| Name | +Type | +Description | +Default | +
|---|---|---|---|
endpoint |
+
+ str
+ |
+ the endpoint |
+ + required + | +
Returns:
+| Type | +Description | +
|---|---|
+ str
+ |
+ a websocket url |
+
qlient/aiohttp/backends.py44 +45 +46 +47 +48 +49 +50 +51 +52 +53 +54 +55 +56 +57 +58 +59 | |
execute_mutation(request)
+
+
+ async
+
+
+Parameters:
+| Name | +Type | +Description | +Default | +
|---|---|---|---|
request |
+
+ GraphQLRequest
+ |
+ + | + required + | +
qlient/aiohttp/backends.py120 +121 +122 +123 +124 +125 +126 +127 +128 +129 | |
execute_query(request)
+
+
+ async
+
+
+Parameters:
+| Name | +Type | +Description | +Default | +
|---|---|---|---|
request |
+
+ GraphQLRequest
+ |
+ + | + required + | +
qlient/aiohttp/backends.py105 +106 +107 +108 +109 +110 +111 +112 +113 +114 +115 +116 +117 +118 | |
execute_subscription(request)
+
+
+ async
+
+
+Parameters:
+| Name | +Type | +Description | +Default | +
|---|---|---|---|
request |
+
+ GraphQLSubscriptionRequest
+ |
+ + | + required + | +
qlient/aiohttp/backends.py131 +132 +133 +134 +135 +136 +137 +138 +139 +140 +141 +142 +143 +144 +145 +146 +147 +148 +149 +150 +151 +152 +153 +154 +155 +156 +157 +158 +159 +160 +161 +162 +163 +164 +165 +166 +167 +168 +169 +170 +171 +172 +173 +174 +175 +176 +177 +178 +179 +180 +181 +182 +183 +184 | |
generate_subscription_id()
+
+
+ classmethod
+
+
+Class method to generate unique subscription ids
+ +Returns:
+| Type | +Description | +
|---|---|
+ str
+ |
+ A unique subscription id |
+
qlient/aiohttp/backends.py35 +36 +37 +38 +39 +40 +41 +42 | |
make_payload(request)
+
+
+ staticmethod
+
+
+Static method for generating the request payload
+ +Parameters:
+| Name | +Type | +Description | +Default | +
|---|---|---|---|
request |
+
+ GraphQLRequest
+ |
+ holds the graphql request |
+ + required + | +
Returns:
+| Type | +Description | +
|---|---|
+ Dict[str, Any]
+ |
+ the payload to send as dictionary |
+
qlient/aiohttp/backends.py61 +62 +63 +64 +65 +66 +67 +68 +69 +70 +71 +72 +73 +74 +75 | |
\n {translation(\"search.result.term.missing\")}: {...missing}\n
\n }\n