Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
36 commits
Select commit Hold shift + click to select a range
3155024
feat: hello world FastAPI service
Flix6x Apr 15, 2025
e28c437
feat: mixing AbstractAuthServer
Flix6x Apr 15, 2025
e0f8175
dev: get a feel for using the mixin
Flix6x Apr 15, 2025
e7500b5
dev: get a better feel for using the mixin
Flix6x Apr 15, 2025
591ffd5
dev: namespace the methods from the abstract class (no longer a pure …
Flix6x Apr 15, 2025
ab598a1
dev: start test, must subclass abstract class
Flix6x Apr 15, 2025
6ec509d
fix: switch to using datamodel-codegen
Flix6x Apr 15, 2025
b95cd25
refactor: rename test module
Flix6x Apr 15, 2025
05b0737
fix: setup TestClient
Flix6x Apr 15, 2025
2640f14
fix: wrong URL
Flix6x Apr 15, 2025
82214df
fix: check response for expected keys
Flix6x Apr 15, 2025
d6a51e9
feat: add test for posting a connection request
Flix6x Apr 15, 2025
923e4b2
docs: add instruction for generating gen_s2_pairing.py
Flix6x Apr 15, 2025
c817a4c
feat: add generated classes for S2 pairing & authentication
Flix6x Apr 15, 2025
55398d7
Merge branch 'refs/heads/fix/use-datamodel-codegen' into feat/fastapi…
Flix6x Apr 15, 2025
a480ab6
Merge remote-tracking branch 'refs/remotes/origin/pairing&auth' into …
Flix6x Apr 15, 2025
ae64071
Merge remote-tracking branch 'refs/remotes/origin/fix/use-datamodel-c…
Flix6x Apr 15, 2025
64bae03
Merge remote-tracking branch 'refs/remotes/origin/pairing&auth' into …
Flix6x Apr 15, 2025
7e60690
Merge remote-tracking branch 'refs/remotes/origin/fix/use-datamodel-c…
Flix6x Apr 15, 2025
31f9de0
fix: add extra testenv requirement
Flix6x Apr 15, 2025
88ae53a
fix: fastapi's testclient requires httpx
Flix6x Apr 15, 2025
6a8d424
style: pylint
Flix6x Apr 15, 2025
1018743
chore: update update_dependencies.sh and run it
Flix6x Apr 15, 2025
8cdc78b
fix: make dev-requirements for Python 3.8
Flix6x Apr 15, 2025
cc1dc10
fix: update dev installation instructions
Flix6x Apr 15, 2025
24ff521
fix: pass json body to the endpoints
Flix6x Apr 15, 2025
14b892a
style: mypy
Flix6x Apr 15, 2025
461b423
Merge remote-tracking branch 'refs/remotes/origin/feat/abstract_clien…
Flix6x May 20, 2025
42d25e4
refactor: change to S2AbstractServer
Flix6x May 20, 2025
1d1c8da
refactor: split up default server class into parts handling tokens an…
Flix6x May 23, 2025
e313100
Merge branch 'refs/heads/dev/refactor-default-server' into feat/fasta…
Flix6x May 23, 2025
d15051a
fix: call actual implementations to handle_pairing_request and handle…
Flix6x May 23, 2025
4965f47
refactor: remove redundant class
Flix6x May 23, 2025
557bd40
refactor: rename custom FastAPI class
Flix6x May 23, 2025
32359f6
dev: remove abstract methods to start and stop the server
Flix6x May 23, 2025
1f64d6c
fix: actually remove abstract methods to start and stop the server
Flix6x May 23, 2025
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion README.rst
Original file line number Diff line number Diff line change
Expand Up @@ -59,7 +59,7 @@ Development

For development, you can install the required dependencies using the following command:

pip install -e .[testing,development]
pip install -e .[testing,development,ws,fastapi]


The tests can be run using tox:
Expand Down
2 changes: 1 addition & 1 deletion ci/update_dependencies.sh
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
#!/usr/bin/env sh

. .venv/bin/activate
pip-compile -U --extra=testing --extra=development --extra=docs -o ./dev-requirements.txt setup.cfg
pip-compile --extra=ws --extra=fastapi --extra=development --extra=docs --extra=testing --output-file=./dev-requirements.txt pyproject.toml
78 changes: 53 additions & 25 deletions dev-requirements.txt
Original file line number Diff line number Diff line change
Expand Up @@ -2,12 +2,16 @@
# This file is autogenerated by pip-compile with Python 3.8
# by the following command:
#
# pip-compile --extra=development --extra=docs --extra=testing --output-file=./dev-requirements.txt setup.cfg
# pip-compile --extra=development --extra=docs --extra=fastapi --extra=testing --extra=ws --output-file=./dev-requirements.txt pyproject.toml
#
alabaster==0.7.13
# via sphinx
annotated-types==0.7.0
# via pydantic
anyio==4.5.2
# via
# httpx
# starlette
argcomplete==3.5.3
# via datamodel-code-generator
astroid==3.2.4
Expand All @@ -21,7 +25,10 @@ build==1.2.2.post1
cachetools==5.5.2
# via tox
certifi==2025.1.31
# via requests
# via
# httpcore
# httpx
# requests
cfgv==3.4.0
# via pre-commit
chardet==5.2.0
Expand All @@ -32,13 +39,13 @@ click==8.1.8
# via
# black
# pip-tools
# s2-python (setup.cfg)
# s2-python (pyproject.toml)
colorama==0.4.6
# via tox
coverage[toml]==7.6.1
# via pytest-cov
datamodel-code-generator==0.27.3
# via s2-python (setup.cfg)
# via s2-python (pyproject.toml)
dill==0.3.9
# via pylint
distlib==0.3.9
Expand All @@ -49,17 +56,30 @@ docutils==0.20.1
# sphinx-rtd-theme
# sphinx-tabs
exceptiongroup==1.2.2
# via pytest
# via
# anyio
# pytest
fastapi==0.115.12
# via s2-python (pyproject.toml)
filelock==3.16.1
# via
# tox
# virtualenv
genson==1.3.0
# via datamodel-code-generator
h11==0.14.0
# via httpcore
httpcore==1.0.8
# via httpx
httpx==0.28.1
# via s2-python (pyproject.toml)
identify==2.6.1
# via pre-commit
idna==3.10
# via requests
# via
# anyio
# httpx
# requests
imagesize==1.4.1
# via sphinx
importlib-metadata==8.5.0
Expand All @@ -83,7 +103,7 @@ markupsafe==2.1.5
mccabe==0.7.0
# via pylint
mypy==1.14.1
# via s2-python (setup.cfg)
# via s2-python (pyproject.toml)
mypy-extensions==1.0.0
# via
# black
Expand All @@ -104,7 +124,7 @@ packaging==24.2
pathspec==0.12.1
# via black
pip-tools==7.4.1
# via s2-python (setup.cfg)
# via s2-python (pyproject.toml)
platformdirs==4.3.6
# via
# black
Expand All @@ -116,44 +136,45 @@ pluggy==1.5.0
# pytest
# tox
pre-commit==3.5.0
# via s2-python (setup.cfg)
# via s2-python (pyproject.toml)
pydantic==2.10.6
# via
# datamodel-code-generator
# s2-python (setup.cfg)
# fastapi
# s2-python (pyproject.toml)
pydantic-core==2.27.2
# via pydantic
pygments==2.19.1
# via
# sphinx
# sphinx-tabs
pylint==3.2.7
# via s2-python (setup.cfg)
# via s2-python (pyproject.toml)
pyproject-api==1.8.0
# via tox
pyproject-hooks==1.2.0
# via
# build
# pip-tools
pyright==1.1.396
# via s2-python (setup.cfg)
# via s2-python (pyproject.toml)
pytest==8.3.5
# via
# pytest-cov
# pytest-timer
# s2-python (setup.cfg)
# s2-python (pyproject.toml)
pytest-cov==5.0.0
# via pytest-cover
pytest-cover==3.0.0
# via pytest-coverage
pytest-coverage==0.0
# via s2-python (setup.cfg)
# via s2-python (pyproject.toml)
pytest-timer==1.0.0
# via s2-python (setup.cfg)
# via s2-python (pyproject.toml)
pytz==2025.1
# via
# babel
# s2-python (setup.cfg)
# s2-python (pyproject.toml)
pyyaml==6.0.2
# via
# datamodel-code-generator
Expand All @@ -162,33 +183,35 @@ requests==2.32.3
# via sphinx
six==1.17.0
# via sphinxcontrib-httpdomain
sniffio==1.3.1
# via anyio
snowballstemmer==2.2.0
# via sphinx
sphinx==7.1.2
# via
# s2-python (setup.cfg)
# s2-python (pyproject.toml)
# sphinx-copybutton
# sphinx-fontawesome
# sphinx-rtd-theme
# sphinx-tabs
# sphinxcontrib-httpdomain
# sphinxcontrib-jquery
sphinx-copybutton==0.5.2
# via s2-python (setup.cfg)
# via s2-python (pyproject.toml)
sphinx-fontawesome==0.0.6
# via s2-python (setup.cfg)
# via s2-python (pyproject.toml)
sphinx-rtd-theme==3.0.2
# via s2-python (setup.cfg)
# via s2-python (pyproject.toml)
sphinx-tabs==3.4.7
# via s2-python (setup.cfg)
# via s2-python (pyproject.toml)
sphinxcontrib-applehelp==1.0.4
# via sphinx
sphinxcontrib-devhelp==1.0.2
# via sphinx
sphinxcontrib-htmlhelp==2.0.1
# via sphinx
sphinxcontrib-httpdomain==1.8.1
# via s2-python (setup.cfg)
# via s2-python (pyproject.toml)
sphinxcontrib-jquery==4.1
# via sphinx-rtd-theme
sphinxcontrib-jsmath==1.0.1
Expand All @@ -197,6 +220,8 @@ sphinxcontrib-qthelp==1.0.3
# via sphinx
sphinxcontrib-serializinghtml==1.1.5
# via sphinx
starlette==0.44.0
# via fastapi
tomli==2.2.1
# via
# black
Expand All @@ -212,19 +237,22 @@ tomli==2.2.1
tomlkit==0.13.2
# via pylint
tox==4.24.1
# via s2-python (setup.cfg)
# via s2-python (pyproject.toml)
types-pytz==2024.2.0.20241221
# via s2-python (setup.cfg)
# via s2-python (pyproject.toml)
typing-extensions==4.12.2
# via
# annotated-types
# anyio
# astroid
# black
# fastapi
# mypy
# pydantic
# pydantic-core
# pylint
# pyright
# starlette
# tox
urllib3==2.2.3
# via requests
Expand All @@ -233,7 +261,7 @@ virtualenv==20.29.2
# pre-commit
# tox
websockets==13.1
# via s2-python (setup.cfg)
# via s2-python (pyproject.toml)
wheel==0.45.1
# via pip-tools
zipp==3.20.2
Expand Down
1 change: 1 addition & 0 deletions pyproject.toml
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,7 @@ flask = [
"Flask",
]
testing = [
"httpx",
"pytest",
"pytest-coverage",
"pytest-timer",
Expand Down
3 changes: 3 additions & 0 deletions src/s2python/authorization/default_server.py
Original file line number Diff line number Diff line change
Expand Up @@ -222,6 +222,9 @@ def _create_encrypted_challenge(

return str(challenge)


class S2DefaultHTTPServer(S2DefaultServer):

def start_server(self) -> None:
"""Start the HTTP server."""

Expand Down
4 changes: 2 additions & 2 deletions src/s2python/authorization/examples/example_s2_server.py
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@
from datetime import datetime, timedelta
from typing import Any

from s2python.authorization.default_server import S2DefaultServer
from s2python.authorization.default_server import S2DefaultHTTPServer
from s2python.generated.gen_s2_pairing import (
S2NodeDescription,
Deployment,
Expand Down Expand Up @@ -71,7 +71,7 @@ def signal_handler(sig: int, frame: Any) -> None:
)

# Create and configure the server
server = S2DefaultServer(
server = S2DefaultHTTPServer(
host=args.host,
http_port=args.http_port,
ws_port=args.ws_port,
Expand Down
31 changes: 31 additions & 0 deletions src/s2python/authorization/fastapi_service.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
try:
from fastapi import FastAPI
except ImportError as exc:
raise ImportError(
"The 'fastapi' package is required. Run 'pip install s2-python[fastapi]' to use this feature."
) from exc

from typing import Any

from s2python.authorization.default_server import S2DefaultServer
from s2python.generated.gen_s2_pairing import ConnectionDetails, ConnectionRequest, PairingResponse, PairingRequest


class S2FastAPI(FastAPI):

def __init__(self, *args: Any, **kwargs: Any):
super().__init__(*args, **kwargs)
self.s2 = S2DefaultServer()


app = S2FastAPI()


@app.post('/requestConnection', response_model=ConnectionDetails)
async def post_request_connection(body: ConnectionRequest) -> ConnectionDetails:
return app.s2.handle_connection_request(body)


@app.post('/requestPairing', response_model=PairingResponse)
async def post_request_pairing(body: PairingRequest) -> PairingResponse:
return app.s2.handle_pairing_request(body)
16 changes: 0 additions & 16 deletions src/s2python/authorization/server.py
Original file line number Diff line number Diff line change
Expand Up @@ -241,19 +241,3 @@ def _create_encrypted_challenge(
Returns:
str: The encrypted challenge
"""

@abc.abstractmethod
def start_server(self) -> None:
"""Start the server.

This method should be implemented by concrete subclasses to start
the server using their preferred web framework.
"""

@abc.abstractmethod
def stop_server(self) -> None:
"""Stop the server.

This method should be implemented by concrete subclasses to stop
the server gracefully.
"""
26 changes: 26 additions & 0 deletions tests/unit/fastapi_test.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
from fastapi.testclient import TestClient

from s2python.authorization.fastapi_service import app


client = TestClient(app)


def test_post_pairing_request():
response = client.post("/requestPairing", json={"hallo": "world"})
assert response.status_code == 200
assert response.json() == {
"requestConnectionUri": None,
"s2ServerNodeId": None,
"serverNodeDescription": None,
}


def test_post_connection_request():
response = client.post("/requestConnection", json={"hallo": "world"})
assert response.status_code == 200
assert response.json() == {
"challenge": None,
"connectionUri": None,
"selectedProtocol": None,
}
1 change: 1 addition & 0 deletions tox.ini
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@ passenv =
extras =
testing
ws
fastapi
commands =
pytest {posargs}

Expand Down
Loading