Skip to content

Commit 287a9e2

Browse files
authored
Add FastAPI binding project base (#1)
1 parent fade28c commit 287a9e2

File tree

13 files changed

+313
-3
lines changed

13 files changed

+313
-3
lines changed
+84
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,84 @@
1+
name: Test FastAPI bindings
2+
3+
on:
4+
push:
5+
branches:
6+
- main
7+
paths:
8+
- "python-fastapi/**"
9+
pull_request:
10+
branches:
11+
- main
12+
paths:
13+
- "python-fastapi/**"
14+
15+
jobs:
16+
test:
17+
runs-on: ubuntu-latest
18+
defaults:
19+
run:
20+
working-directory: python-fastapi
21+
strategy:
22+
matrix:
23+
python-version:
24+
- "3.9"
25+
- "3.10"
26+
- "3.11"
27+
- "3.12"
28+
- "3.13"
29+
30+
steps:
31+
- uses: actions/checkout@v4
32+
33+
- name: Install uv and set the python version
34+
uses: astral-sh/setup-uv@v5
35+
with:
36+
version: "0.6.2"
37+
python-version: ${{ matrix.python-version }}
38+
39+
- name: Run tests
40+
run: uv run python -m unittest discover -s tests -v
41+
42+
find-examples:
43+
runs-on: ubuntu-latest
44+
outputs:
45+
matrix: ${{ steps.set-matrix.outputs.matrix }}
46+
steps:
47+
- uses: actions/checkout@v4
48+
49+
- name: Find all examples to test
50+
id: set-matrix
51+
working-directory: python-fastapi
52+
run: |
53+
examples=$(find examples -mindepth 1 -maxdepth 1 -type d -exec basename {} \;)
54+
if [ -z "$examples" ]; then
55+
echo "No examples found"
56+
examples="[]"
57+
else
58+
examples=$(echo $examples | jq -R 'split(" ")' | jq -c '.')
59+
fi
60+
matrix=$(jq -c -n --argjson examples "$examples" '{example: $examples}')
61+
echo "matrix=${matrix}" >> $GITHUB_OUTPUT
62+
63+
test-examples:
64+
runs-on: ubuntu-latest
65+
needs: find-examples
66+
strategy:
67+
matrix: ${{fromJson(needs.find-examples.outputs.matrix)}}
68+
defaults:
69+
run:
70+
working-directory: python-fastapi/examples/${{ matrix.example }}
71+
steps:
72+
- uses: actions/checkout@v4
73+
74+
- name: Load Python version from .python-version
75+
run: echo "PYTHON_VERSION=$(cat .python-version)" >> $GITHUB_ENV
76+
77+
- name: Install uv
78+
uses: astral-sh/setup-uv@v5
79+
with:
80+
version: "0.6.2"
81+
python-version: ${{ env.PYTHON_VERSION }}
82+
83+
- name: Test "${{ matrix.example }}"
84+
run: uv run python -m unittest -v

.gitignore python-fastapi/.gitignore

+3-3
Original file line numberDiff line numberDiff line change
@@ -85,7 +85,7 @@ ipython_config.py
8585
# pyenv
8686
# For a library or package, you might want to ignore these files since the code is
8787
# intended to run in multiple environments; otherwise, check them in:
88-
# .python-version
88+
/.python-version
8989

9090
# pipenv
9191
# According to pypa/pipenv#598, it is recommended to include Pipfile.lock in version control.
@@ -98,7 +98,7 @@ ipython_config.py
9898
# Similar to Pipfile.lock, it is generally recommended to include uv.lock in version control.
9999
# This is especially recommended for binary packages to ensure reproducibility, and is more
100100
# commonly ignored for libraries.
101-
#uv.lock
101+
/uv.lock
102102

103103
# poetry
104104
# Similar to Pipfile.lock, it is generally recommended to include poetry.lock in version control.
@@ -165,7 +165,7 @@ cython_debug/
165165
# be found at https://github.com/github/gitignore/blob/main/Global/JetBrains.gitignore
166166
# and can be added to the global gitignore or merged into this file. For a more nuclear
167167
# option (not recommended) you can uncomment the following to ignore the entire idea folder.
168-
#.idea/
168+
/.idea/
169169

170170
# PyPI configuration file
171171
.pypirc

python-fastapi/README.md

+11
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
# gel-auth-fastapi
2+
3+
Gel auth extension binding for FastAPI.
4+
5+
## Usage
6+
7+
## Development
8+
9+
```console
10+
$ uv run python -m unittest discover -s tests
11+
```
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
3.13
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
# Basic Async Example
2+
3+
```console
4+
$ uv run main.py
5+
```
6+
7+
## Development
8+
9+
```console
10+
$ uv run python -m unittest
11+
```
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
import gel_auth_fastapi
2+
3+
4+
def main():
5+
print("Hello from gel-auth-fastapi-basic-async!")
6+
print(gel_auth_fastapi.__path__)
7+
8+
9+
if __name__ == "__main__":
10+
main()
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
[project]
2+
name = "gel-auth-fastapi-basic-async"
3+
version = "0.1.0"
4+
description = "Basic async example project"
5+
readme = "README.md"
6+
requires-python = ">=3.13"
7+
dependencies = [
8+
"gel-auth-fastapi",
9+
]
10+
11+
[tool.uv.sources]
12+
gel-auth-fastapi = { path = "../../" }
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
import unittest
2+
3+
import main
4+
5+
6+
class TestMain(unittest.TestCase):
7+
def test_main(self):
8+
main.main()

python-fastapi/examples/basic-async/uv.lock

+27
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

python-fastapi/pyproject.toml

+41
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,41 @@
1+
[project]
2+
name = "gel-auth-fastapi"
3+
version = "0.1.0"
4+
description = "Gel auth extension binding for FastAPI"
5+
readme = "README.md"
6+
authors = [
7+
{ name = "Gel Data Inc.", email = "[email protected]" }
8+
]
9+
requires-python = ">=3.9"
10+
dependencies = []
11+
12+
[build-system]
13+
requires = ["hatchling"]
14+
build-backend = "hatchling.build"
15+
16+
[dependency-groups]
17+
dev = [
18+
"mypy>=1.15.0",
19+
"ruff>=0.9.7",
20+
]
21+
22+
[tool.mypy]
23+
exclude = [
24+
"^.eggs",
25+
"^.github",
26+
"^.vscode",
27+
"^build",
28+
"^dist",
29+
"^docs",
30+
"^target",
31+
]
32+
files = "."
33+
python_version = "3.9"
34+
35+
[tool.ruff]
36+
line-length = 80
37+
indent-width = 4
38+
39+
[tool.black]
40+
line-length = 80
41+
target-version = ["py39", "py310", "py311", "py312", "py313"]
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
#
2+
# This source file is part of the Gel open source project.
3+
#
4+
# Copyright 2025-present Gel Data Inc. and the Gel authors.
5+
#
6+
# Licensed under the Apache License, Version 2.0 (the "License");
7+
# you may not use this file except in compliance with the License.
8+
# You may obtain a copy of the License at
9+
#
10+
# http://www.apache.org/licenses/LICENSE-2.0
11+
#
12+
# Unless required by applicable law or agreed to in writing, software
13+
# distributed under the License is distributed on an "AS IS" BASIS,
14+
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15+
# See the License for the specific language governing permissions and
16+
# limitations under the License.
17+
#

python-fastapi/src/gel_auth_fastapi/py.typed

Whitespace-only changes.

python-fastapi/tests/test_cqa.py

+88
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,88 @@
1+
#
2+
# This source file is part of the Gel open source project.
3+
#
4+
# Copyright 2025-present Gel Data Inc. and the Gel authors.
5+
#
6+
# Licensed under the Apache License, Version 2.0 (the "License");
7+
# you may not use this file except in compliance with the License.
8+
# You may obtain a copy of the License at
9+
#
10+
# http://www.apache.org/licenses/LICENSE-2.0
11+
#
12+
# Unless required by applicable law or agreed to in writing, software
13+
# distributed under the License is distributed on an "AS IS" BASIS,
14+
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15+
# See the License for the specific language governing permissions and
16+
# limitations under the License.
17+
#
18+
19+
import pathlib
20+
import subprocess
21+
import sys
22+
import unittest
23+
24+
25+
def find_root_path() -> pathlib.Path:
26+
return pathlib.Path(__file__).parent.parent
27+
28+
29+
class TestSourceCode(unittest.TestCase):
30+
def test_cqa_mypy(self) -> None:
31+
root_path = find_root_path()
32+
config_path = root_path / "pyproject.toml"
33+
if not config_path.exists():
34+
raise RuntimeError("could not locate pyproject.toml file")
35+
36+
try:
37+
import mypy # NoQA
38+
except ImportError:
39+
raise unittest.SkipTest("mypy module is missing")
40+
41+
for subdir in ["src", "tests"]:
42+
with self.subTest(subdir=subdir):
43+
try:
44+
subprocess.run(
45+
[
46+
sys.executable,
47+
"-m",
48+
"mypy",
49+
"--config-file",
50+
config_path,
51+
subdir,
52+
],
53+
check=True,
54+
stdout=subprocess.PIPE,
55+
stderr=subprocess.PIPE,
56+
cwd=root_path,
57+
)
58+
except subprocess.CalledProcessError as ex:
59+
output = ex.stdout.decode()
60+
if ex.stderr:
61+
output += "\n\n" + ex.stderr.decode()
62+
raise AssertionError(
63+
f"mypy validation failed:\n{output}"
64+
) from None
65+
66+
def test_cqa_ruff(self):
67+
root_path = find_root_path()
68+
69+
try:
70+
import ruff # type: ignore # NoQA
71+
except ImportError:
72+
raise unittest.SkipTest("ruff module is missing")
73+
74+
for subdir in ["src", "tests"]:
75+
with self.subTest(subdir=subdir):
76+
try:
77+
subprocess.run(
78+
["ruff", "check", subdir],
79+
check=True,
80+
stdout=subprocess.PIPE,
81+
stderr=subprocess.PIPE,
82+
cwd=root_path,
83+
)
84+
except subprocess.CalledProcessError as ex:
85+
output = ex.output.decode()
86+
raise AssertionError(
87+
f"ruff validation failed:\n{output}"
88+
) from None

0 commit comments

Comments
 (0)