Skip to content

Commit ec6da3a

Browse files
committed
feat: add intial python wrapper
0 parents  commit ec6da3a

47 files changed

Lines changed: 28736 additions & 0 deletions

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

.github/workflows/ci.yml

Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,28 @@
1+
name: PlayerDataPy CI
2+
3+
on:
4+
pull_request:
5+
types: [opened, synchronize, reopened, ready_for_review]
6+
push:
7+
branches: [ main ]
8+
9+
concurrency:
10+
group: ${{ github.workflow }}-${{ github.ref }}
11+
cancel-in-progress: true
12+
13+
jobs:
14+
lint:
15+
name: Lint
16+
secrets: inherit
17+
uses: "./.github/workflows/lint.yml"
18+
19+
test:
20+
name: Test
21+
secrets: inherit
22+
uses: "./.github/workflows/test.yml"
23+
24+
release:
25+
name: Release
26+
secrets: inherit
27+
needs: [lint, test]
28+
uses: "./.github/workflows/release.yml"

.github/workflows/lint.yml

Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,35 @@
1+
name: PlayerDataPy Lint
2+
3+
on:
4+
workflow_call: {}
5+
6+
jobs:
7+
lint:
8+
name: Lint
9+
runs-on: ubuntu-latest
10+
permissions:
11+
contents: read
12+
13+
steps:
14+
- uses: actions/checkout@v6
15+
16+
- uses: actions/setup-python@v6
17+
with:
18+
python-version: '3.12'
19+
20+
- name: Install uv
21+
id: setup-uv
22+
uses: astral-sh/setup-uv@v6.6.1
23+
with:
24+
enable-cache: true
25+
cache-suffix: '-venv-lint'
26+
activate-environment: true
27+
28+
- name: Install Dependencies
29+
run: uv sync --locked
30+
31+
- name: Format Check (Black)
32+
run: uv run --no-sync black . --check
33+
34+
- name: Import Cleanup Check (Autoflake)
35+
run: uv run --no-sync pautoflake ./ --check --quiet

.github/workflows/release.yml

Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,34 @@
1+
name: PlayerDataPy Release
2+
3+
on:
4+
workflow_call:
5+
outputs:
6+
new_release_published:
7+
value: ${{ jobs.release.outputs.new_release_published }}
8+
new_release_version:
9+
value: ${{ jobs.release.outputs.new_release_version }}
10+
11+
permissions:
12+
contents: write
13+
pull-requests: write
14+
issues: write
15+
16+
jobs:
17+
release:
18+
name: Release
19+
runs-on: ubuntu-latest
20+
21+
steps:
22+
- uses: actions/checkout@v5
23+
with:
24+
fetch-depth: 0
25+
26+
- name: Semantic Release
27+
id: semantic-release
28+
uses: cycjimmy/semantic-release-action@v4
29+
env:
30+
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
31+
32+
outputs:
33+
new_release_published: ${{ steps.semantic-release.outputs.new_release_published }}
34+
new_release_version: ${{ steps.semantic-release.outputs.new_release_version }}

.github/workflows/test.yml

Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,32 @@
1+
name: PlayerDataPy Test
2+
3+
on:
4+
workflow_call: {}
5+
6+
jobs:
7+
test:
8+
name: Test
9+
runs-on: ubuntu-latest
10+
permissions:
11+
contents: read
12+
13+
steps:
14+
- uses: actions/checkout@v6
15+
16+
- uses: actions/setup-python@v6
17+
with:
18+
python-version: '3.12'
19+
20+
- name: Install uv
21+
id: setup-uv
22+
uses: astral-sh/setup-uv@v6.6.1
23+
with:
24+
enable-cache: true
25+
cache-suffix: '-venv-test'
26+
activate-environment: true
27+
28+
- name: Install Dependencies
29+
run: uv sync --locked
30+
31+
- name: Run Tests
32+
run: uv run --no-sync pytest

.gitignore

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,24 @@
1+
__pycache__/
2+
3+
.token
4+
.vscode
5+
.vscode
6+
.python-version
7+
key.json
8+
.DS_Store
9+
venv
10+
.venv
11+
.idea
12+
__pycache__
13+
__PYCACHE__
14+
.pytest_cache
15+
.mypy_cache
16+
.ipynb_checkpoints
17+
*.egg-info/
18+
*.pyc
19+
*.mp4
20+
*.rrd
21+
*.edgeblob
22+
*.glb
23+
.coverage
24+
.token

.releaserc.json

Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,34 @@
1+
{
2+
"branches": ["main"],
3+
"plugins": [
4+
[
5+
"@semantic-release/commit-analyzer",
6+
{
7+
"preset": "angular",
8+
"releaseRules": [
9+
{
10+
"type": "chore",
11+
"release": "patch"
12+
},
13+
{
14+
"type": "feat",
15+
"release": "minor"
16+
},
17+
{
18+
"type": "fix",
19+
"release": "patch"
20+
}
21+
]
22+
}
23+
],
24+
"@semantic-release/release-notes-generator",
25+
[
26+
"@semantic-release/github",
27+
{
28+
"successComment": false,
29+
"failComment": false,
30+
"failTitle": false
31+
}
32+
]
33+
]
34+
}

CODEOWNERS

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
* @playerdata/data-analysis

LICENSE

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
MIT License
2+
3+
Copyright (c) 2026 PlayerData
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.

README.md

Lines changed: 86 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,86 @@
1+
# GQL python
2+
A python package for interacting with the PlayerData GraphQL API.
3+
4+
## Folder Structure
5+
- `playerdata_api`: The main package for interacting with the PlayerData API.
6+
- `gqlauth`: The main package for authenticating with the PlayerData API.
7+
- `gqlclient`: The main package for interacting with the PlayerData GraphQL API.
8+
- `custom_queries`: Custom queries for the PlayerData GraphQL API.
9+
- `custom_mutations`: Custom mutations for the PlayerData GraphQL API.
10+
- `custom_fields`: Custom fields for the PlayerData GraphQL API.
11+
- `input_types`: Input types for the PlayerData GraphQL API.
12+
- `enums`: Enums for the PlayerData GraphQL API.
13+
- `custom_typing_fields`: Custom typing fields for the PlayerData GraphQL API.
14+
- `custom_responses`: Custom responses for the PlayerData GraphQL API.
15+
16+
## Installation
17+
18+
uv is the tool we use to build and manage the `playerdatapy` Python package.
19+
20+
Make sure you install uv using [pipx](https://docs.astral.sh/uv/getting-started/installation/#pypi) or the [official installer](https://docs.astral.sh/uv/getting-started/installation/#standalone-installer). Installing with pip or other methods will lead to unexpected behavior.
21+
22+
We recommend using the [official installer](https://docs.astral.sh/uv/getting-started/installation/#standalone-installer).
23+
24+
Then you can install the required dependencies, in a virtual environment if required.
25+
26+
```bash
27+
uv sync
28+
```
29+
30+
## Usage
31+
32+
To use the GraphqlClient, you need to provide your client id, this will be provided to you by PlayerData.
33+
To request API credentials, please contact the PlayerData team at support@playerdata.co.uk.
34+
35+
36+
### Option 1: Use generated types with PlayerDataAPI
37+
38+
Example usage of this option is provided in the `example_pydantic.py` file.
39+
The basic flow is to create a PlayerDataAPI instance, build the query objects using the code-generated Pydantic models (generated by ariadne-codegen), and then call the run_queries method.
40+
41+
To run an example of this option, you can use the following command:
42+
43+
```bash
44+
python example_pydantic.py
45+
```
46+
47+
### Option 2: Use the GraphqlClient class directly
48+
49+
Example usage of this option is provided in the `example_direct.py` file.
50+
The basic flow is to create a GraphqlClient instance, build the query string, and then call the query method.
51+
52+
To run an example of this option, you can use the following command:
53+
54+
```bash
55+
python example_direct.py
56+
```
57+
58+
## Authentication Types
59+
60+
These authentication types are set out in the `playerdatapy.gqlauth.AuthenticationType` enum.
61+
The default authentication type is `AuthenticationType.AUTHORISATION_CODE_FLOW`.
62+
These authentication types are used to set the authentication type in the `GraphqlAuth` class.
63+
64+
### Authorisation Code Flow (PKCE)
65+
66+
Authorisation code flow with PKCE is used to authenticate users with non_confidential credentials.
67+
68+
### Authorisation Code Flow
69+
70+
Authorisation code flow is used to authenticate users with confidential credentials.
71+
72+
### Client Credentials Flow
73+
74+
Client credentials flow is used to authenticate backend to backend communication.
75+
76+
### Updates to the API Fields and Mutations
77+
78+
To update the API fields and mutations, you need to set an `AUTH_TOKEN` environment variable.
79+
This code is auto-generated by Ariadne, so any changes to the API fields and mutations will be reflected in the code.
80+
81+
```shell
82+
export AUTH_TOKEN=f"Bearer {your_auth_token}"
83+
python -m ariadne-codegen
84+
```
85+
86+
This will generate code and update files in the `playerdatapy` package.

example_direct.py

Lines changed: 42 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,42 @@
1+
from playerdatapy.gqlauth import GraphqlAuth
2+
from playerdatapy.gqlclient import Client
3+
from playerdatapy.gqlauth import AuthenticationType
4+
import asyncio
5+
6+
# Build out the query string.
7+
# Our GraphiQL Playground at https://app.playerdata.co.uk/api/graphiql/ is useful for building out and testing the query.
8+
CLIENT_ID = "your_client_id"
9+
CLIENT_SECRET = "your_client_secret"
10+
11+
example_query = """
12+
query Session($session_id: ID!) {
13+
session(id: $session_id) {
14+
id
15+
startTime
16+
endTime
17+
}
18+
}
19+
"""
20+
21+
async def main(session_id: str):
22+
auth = GraphqlAuth(
23+
client_id=CLIENT_ID,
24+
client_secret=CLIENT_SECRET,
25+
type=AuthenticationType.CLIENT_CREDENTIALS_FLOW,
26+
)
27+
client = Client(
28+
url="https://app.playerdata.co.uk/api/graphql",
29+
headers={"Authorization": f"Bearer {auth._get_authentication_token()}"},
30+
)
31+
response = await client.execute(
32+
query=example_query,
33+
variables={"session_id": session_id},
34+
)
35+
result = client.get_data(response)
36+
return result["session"]
37+
38+
39+
if __name__ == "__main__":
40+
session_id = "an_example_session_id"
41+
result = asyncio.run(main(session_id))
42+
print(result)

0 commit comments

Comments
 (0)