Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

fix statics #157

Merged
merged 6 commits into from
Oct 17, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
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
33 changes: 0 additions & 33 deletions .github/workflows/scheduled.yml
Original file line number Diff line number Diff line change
Expand Up @@ -22,39 +22,6 @@ env:
UV_CACHE_DIR: /tmp/.uv-cache

jobs:
# https://twitter.com/mycoliza/status/1571295690063753218
nightly:
runs-on: ubuntu-latest
name: ubuntu / 3.14-dev
steps:
- uses: actions/checkout@v4
with:
submodules: true
- name: Set up uv
run: curl -LsSf https://astral.sh/uv/${{ env.UV_VERSION }}/install.sh | sh
- name: Install python
uses: actions/setup-python@v5
with:
python-version: "3.14-dev"
- name: Restore uv cache
uses: actions/cache@v4
with:
path: /tmp/.uv-cache
key: uv-${{ runner.os }}-${{ hashFiles('uv.lock') }}
restore-keys: |
uv-${{ runner.os }}-${{ hashFiles('uv.lock') }}
uv-${{ runner.os }}
- run: python --version
- name: uv lock
if: hashFiles('uv.lock') == ''
run: uv lock
- name: uv sync --dev
run: uv sync --dev
- name: make test
run: make test

- name: Minimize uv cache
run: uv cache prune --ci
# https://twitter.com/alcuadrado/status/1571291687837732873
update:
# This action checks that updating the dependencies of this crate to the latest available that
Expand Down
2 changes: 1 addition & 1 deletion .pre-commit-config.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@ repos:
stages: [commit]
- repo: https://github.com/astral-sh/ruff-pre-commit
# Ruff version.
rev: v0.3.2
rev: v0.6.9
hooks:
# Run the linter.
- id: ruff
Expand Down
4 changes: 4 additions & 0 deletions Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -188,3 +188,7 @@ lint-dependencies: lint-deptry lint-deptrac

watch-lint-deptrac:
${INVENV} watchfiles "deptracpy" deptracpy.yaml src

run-traefik:
@echo "Remember to set SALDO_WS__APP__ROOT_PATH=/ws/saldo-ws"
traefik --configFile=contrib/traefik/traefik.toml
20 changes: 20 additions & 0 deletions contrib/traefik/routes.toml
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
[http]
[http.middlewares]

[http.middlewares.api-stripprefix.stripPrefix]
prefixes = ["/ws/saldo-ws"]

[http.routers]

[http.routers.app-http]
entryPoints = ["http"]
service = "app"
rule = "PathPrefix(`/ws/saldo-ws`)"
middlewares = ["api-stripprefix"]

[http.services]

[http.services.app]
[http.services.app.loadBalancer]
[[http.services.app.loadBalancer.servers]]
url = "http://127.0.0.1:8000"
7 changes: 7 additions & 0 deletions contrib/traefik/traefik.toml
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
[entryPoints]
[entryPoints.http]
address = ":9999"

[providers]
[providers.file]
filename = "contrib/traefik/routes.toml"
2 changes: 2 additions & 0 deletions pyproject.toml
Original file line number Diff line number Diff line change
Expand Up @@ -48,4 +48,6 @@ dev-dependencies = [
"pytest-cov>=5.0.0",
"ruff>=0.6.9",
"syrupy>=4.7.2",
"uvicorn>=0.32.0",
"watchfiles>=0.24.0",
]
3 changes: 3 additions & 0 deletions src/sblex/saldo_ws/routes/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@
inflection,
lids,
paradigms,
statics,
system_info,
)

Expand All @@ -22,3 +23,5 @@
router.include_router(inflection.router, prefix="/gen", tags=["inflection"])
router.include_router(paradigms.router, prefix="/para", tags=["paradigms"])
router.include_router(system_info.router, tags=["system-info"])
# Workaround for fastapi.staticfiles.StaticFiles not working
router.include_router(statics.router)
9 changes: 9 additions & 0 deletions src/sblex/saldo_ws/routes/statics.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
from fastapi import APIRouter
from fastapi.responses import FileResponse

router = APIRouter()


@router.get("/static{path:path}", name="static")
async def staticfiles_workaround(path: str) -> FileResponse:
return FileResponse(path=f"static{path}")
5 changes: 3 additions & 2 deletions src/sblex/saldo_ws/server.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,6 @@
from fastapi import FastAPI
from fastapi.middleware.cors import CORSMiddleware
from fastapi.responses import ORJSONResponse
from fastapi.staticfiles import StaticFiles
from opentelemetry.instrumentation.fastapi import FastAPIInstrumentor
from opentelemetry.instrumentation.httpx import HTTPXClientInstrumentor

Expand Down Expand Up @@ -73,6 +72,8 @@ def create_saldo_ws_server(*, settings: config.Settings) -> FastAPI:
FastAPIInstrumentor.instrument_app(webapp)

webapp.include_router(routes.router)
webapp.mount("/static", StaticFiles(directory="static"), name="static")
# Workaround for fastapi.staticfiles.StaticFiles not working,
# added in saldo_ws.routes instead
# webapp.mount("/static", StaticFiles(directory="static"), name="static")

return webapp
9 changes: 9 additions & 0 deletions src/sblex/sblex_server/routes/statics.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
from fastapi import APIRouter
from fastapi.responses import FileResponse

router = APIRouter()


@router.get("/static{path:path}", response_class=FileResponse, name="static")
async def staticfiles_workaround(path: str):
return f"static{path}"
36 changes: 35 additions & 1 deletion tests/e2e/conftest.py
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@
from sblex.fm.fm_runner import FmRunner
from sblex.fm_server.config import Settings as FmSettings
from sblex.fm_server.server import create_fm_server
from sblex.saldo_ws.config import FmBinSettings, MatomoSettings
from sblex.saldo_ws.config import AppSettings, FmBinSettings, MatomoSettings
from sblex.saldo_ws.config import Settings as SaldoWsSettings
from sblex.saldo_ws.deps import get_fm_client, get_fm_runner
from sblex.saldo_ws.server import create_saldo_ws_server
Expand All @@ -23,6 +23,30 @@ def snapshot_json(snapshot):
return snapshot.with_defaults(extension_class=JSONSnapshotExtension)


@pytest.fixture(name="webapp_w_root_path")
def fixture_webapp_w_root_path(fm_client: AsyncClient) -> FastAPI:
webapp = create_saldo_ws_server(
settings=SaldoWsSettings(
semantic_path="assets/testing/saldo.txt",
fm_server_url="not-used",
fm_bin=FmBinSettings(path="not used"),
tracking=MatomoSettings(matomo_url=None),
otel=OTelSettings(
otel_service_name="saldo-ws",
debug_log_otel_to_console=False,
debug_log_otel_to_provider=False,
),
app=AppSettings(root_path="/ws/saldo-ws"),
)
# config={
# "semantic.path": "assets/testing/saldo.txt",
# "morphology.path": "assets/testing/saldo.lex",
# },
# env=env,
)
return webapp


@pytest.fixture(name="webapp")
def fixture_webapp(fm_client: AsyncClient) -> FastAPI:
webapp = create_saldo_ws_server(
Expand Down Expand Up @@ -353,6 +377,16 @@ async def client(webapp: FastAPI) -> AsyncGenerator[AsyncClient, None]:
yield client


@pytest_asyncio.fixture
async def client_w_root_path(webapp_w_root_path: FastAPI) -> AsyncGenerator[AsyncClient, None]:
async with LifespanManager(webapp_w_root_path):
async with AsyncClient(
transport=ASGITransport(webapp_w_root_path), # type: ignore [arg-type]
base_url="http://testserver",
) as client:
yield client


@pytest.fixture(name="fm_server")
def fixture_fm_server() -> FastAPI:
return create_fm_server(
Expand Down
17 changes: 17 additions & 0 deletions tests/e2e/saldo_ws/test_static_files.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
import pytest
from fastapi import status
from httpx import AsyncClient


class TestStaticRoutes:
@pytest.mark.asyncio
async def test_static_saldo_css_returns_200(self, client: AsyncClient) -> None:
res = await client.get("/static/saldo.css")
assert res.status_code == status.HTTP_200_OK

@pytest.mark.asyncio
async def test_root_path_and_static_saldo_css_returns_200(
self, client_w_root_path: AsyncClient
) -> None:
res = await client_w_root_path.get("/static/saldo.css")
assert res.status_code == status.HTTP_200_OK
Loading