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

85 port gen json api #95

Merged
merged 7 commits into from
Mar 15, 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
2 changes: 1 addition & 1 deletion mypy.ini
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
[mypy]
mypy_path = src,tests
mypy_path = src
namespace_packages = True
explicit_package_bases = True
show_error_codes = True
Expand Down
4 changes: 2 additions & 2 deletions src/sblex/application/queries/__init__.py
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
from sblex.application.queries.fullforms import FullformQuery
from sblex.application.queries.inflection import GenerateInflectionTable
from sblex.application.queries.inflection import InflectionTableQuery
from sblex.application.queries.lex_fullforms import FullformLexQuery
from sblex.application.queries.lookup_lid import LookupLid

__all__ = ["FullformLexQuery", "LookupLid", "FullformQuery", "GenerateInflectionTable"]
__all__ = ["FullformLexQuery", "LookupLid", "FullformQuery", "InflectionTableQuery"]
6 changes: 3 additions & 3 deletions src/sblex/application/queries/inflection.py
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import abc
from typing import Iterable, TypedDict
from typing import TypedDict


class InflectionTableRow(TypedDict):
Expand All @@ -11,6 +11,6 @@ class InflectionTableRow(TypedDict):
p: str


class GenerateInflectionTable(abc.ABC):
class InflectionTableQuery(abc.ABC):
@abc.abstractmethod
def query(self, paradigm: str, word: str) -> Iterable[InflectionTableRow]: ...
def query(self, paradigm: str, word: str) -> list[InflectionTableRow]: ...
14 changes: 7 additions & 7 deletions src/sblex/infrastructure/queries/fm_runner_inflection.py
Original file line number Diff line number Diff line change
@@ -1,22 +1,22 @@
from typing import Iterable

from sblex.application.queries import GenerateInflectionTable
from sblex.application.queries import InflectionTableQuery
from sblex.application.queries.inflection import InflectionTableRow
from sblex.fm import FmRunner


class FmRunnerInflectionTable(GenerateInflectionTable):
class FmRunnerInflectionTable(InflectionTableQuery):
def __init__(self, *, fm_runner: FmRunner) -> None:
super().__init__()
self.fm_runner = fm_runner

def query(self, paradigm: str, word: str) -> Iterable[InflectionTableRow]:
for row in self.fm_runner.inflection(paradigm, word):
yield {
def query(self, paradigm: str, word: str) -> list[InflectionTableRow]:
return [
{
"form": row["word"],
"gf": row["head"],
"pos": row["pos"],
"inhs": row["inhs"],
"msd": row["param"],
"p": row["p"],
}
for row in self.fm_runner.inflection(paradigm, word)
]
10 changes: 8 additions & 2 deletions src/sblex/saldo_ws/config.py
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
from pathlib import Path
from typing import Optional

from pydantic import BaseModel
Expand All @@ -23,9 +24,15 @@
tracking: MatomoSettings = MatomoSettings()


class FmBinSettings(BaseModel):
path: Path
locale: str | None = None


class Settings(BaseSettings):
semantic_path: str
fm_server_url: str
fm_bin: FmBinSettings
otel: OTelSettings
app: AppSettings = AppSettings()
frontend: FrontendSettings = FrontendSettings()
Expand All @@ -37,5 +44,4 @@

def read_settings_from_env() -> Settings:
otel = OTelSettings(_env_prefix="SALDO_WS__")
settings = Settings(otel=otel)
return settings
return Settings(otel=otel)

Check warning on line 47 in src/sblex/saldo_ws/config.py

View check run for this annotation

Codecov / codecov/patch

src/sblex/saldo_ws/config.py#L47

Added line #L47 was not covered by tests
13 changes: 13 additions & 0 deletions src/sblex/saldo_ws/deps.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,9 +3,12 @@
import httpx
from fastapi import Depends, Request
from sblex.application.queries import FullformLexQuery, FullformQuery, LookupLid
from sblex.application.queries.inflection import InflectionTableQuery
from sblex.application.services import LookupService
from sblex.fm import Morphology
from sblex.fm.fm_runner import FmRunner
from sblex.infrastructure.queries import LookupFullformLexQuery
from sblex.infrastructure.queries.fm_runner_inflection import FmRunnerInflectionTable
from sblex.infrastructure.queries.http_morpology import HttpMorphology


Expand All @@ -30,6 +33,10 @@
return LookupService(morphology=morphology, lookup_lid=lookup_lid)


def get_fm_runner(request: Request) -> FmRunner:
return request.app.state._fm_runner

Check warning on line 37 in src/sblex/saldo_ws/deps.py

View check run for this annotation

Codecov / codecov/patch

src/sblex/saldo_ws/deps.py#L37

Added line #L37 was not covered by tests


def get_fullform_query() -> FullformQuery:
query = mock.Mock(spec=FullformQuery)
query.query = mock.Mock(return_value=b'{"c":"a"}')
Expand All @@ -40,3 +47,9 @@
lookup_service: LookupService = Depends(get_lookup_service), # noqa: B008
) -> FullformLexQuery:
return LookupFullformLexQuery(lookup_service=lookup_service)


def get_inflection_table_query(
fm_runner: FmRunner = Depends(get_fm_runner), # noqa: B008
) -> InflectionTableQuery:
return FmRunnerInflectionTable(fm_runner=fm_runner)
3 changes: 2 additions & 1 deletion src/sblex/saldo_ws/routes/__init__.py
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
from fastapi import APIRouter
from sblex.saldo_ws.routes import compounds, fullform, fullform_lex, lids
from sblex.saldo_ws.routes import compounds, fullform, fullform_lex, inflection, lids

router = APIRouter()

Expand All @@ -10,3 +10,4 @@
router.include_router(
compounds.router, prefix="/sms", tags=["sms", "sammansättning", "compound"]
)
router.include_router(inflection.router, prefix="/gen", tags=["inflection"])
26 changes: 26 additions & 0 deletions src/sblex/saldo_ws/routes/inflection.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
import sys

from fastapi import APIRouter, Depends
from fastapi.responses import ORJSONResponse
from opentelemetry import trace
from sblex.application.queries.inflection import InflectionTableQuery
from sblex.saldo_ws import deps, schemas

router = APIRouter()


@router.get(
"/json/{paradigm}/{word}",
response_model=list[schemas.InflectionRow],
response_class=ORJSONResponse,
name="inflections:gen-json",
)
async def inflection_table_json(
paradigm: str,
word: str,
inflection_table_query: InflectionTableQuery = Depends(deps.get_inflection_table_query), # noqa: B008
) -> ORJSONResponse:
with trace.get_tracer(__name__).start_as_current_span(
sys._getframe().f_code.co_name
) as _process_api_span:
return ORJSONResponse(inflection_table_query.query(paradigm, word))
9 changes: 9 additions & 0 deletions src/sblex/saldo_ws/schemas.py
Original file line number Diff line number Diff line change
Expand Up @@ -13,3 +13,12 @@ class FullformLex(BaseModel):
l: Lemma # noqa: E741
gf: str
p: str


class InflectionRow(BaseModel):
form: str
head: str
pos: str
inhs: list[str]
msd: str
p: str
8 changes: 8 additions & 0 deletions src/sblex/saldo_ws/tasks.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
import httpx
from fastapi import FastAPI
from sblex.fm import MemMorphology
from sblex.fm.fm_runner import FmRunner
from sblex.infrastructure.queries import MemLookupLid

logger = logging.getLogger(__name__)
Expand All @@ -30,11 +31,18 @@ def load_morphology(app: FastAPI) -> None:
app.state._morph = morphology


def setup_fmrunner(app: FastAPI) -> None:
logger.info("setup fm-runner")
fm_runner = FmRunner(app.state.settings.fm_bin.path, locale=app.state.settings.fm_bin.locale)
app.state._fm_runner = fm_runner


@asynccontextmanager
async def lifespan(app: FastAPI):
logger.info("startup")
app.state._fm_client = httpx.AsyncClient(base_url=app.state.settings.fm_server_url)
load_lookup_lid(app)
setup_fmrunner(app)
yield
await app.state._fm_client.aclose()
logger.info("shutdown")
17 changes: 0 additions & 17 deletions src/sblex/table.py
Original file line number Diff line number Diff line change
Expand Up @@ -14,23 +14,6 @@ def function(format, paradigm, word):
j = cjson.decode(utf8.d(result))
if format == "html":
result = htmlize(paradigm, word, j)
elif format == "json":
result = "[\n"
result += ",\n".join(
[
'{"form":"%s","gf":"%s","pos":"%s","is":[%s],"msd":"%s","p":"%s"}'
% (
x["word"],
x["head"],
x["pos"],
", ".join(['"%s"' % (i) for i in x["inhs"]]),
x["param"],
utf8.d(paradigm),
)
for x in j
]
)
result += "\n]"
elif format == "xml":
result = xmlize(paradigm, j)
result_code = apache.OK
Expand Down
Empty file added tests/__init__.py
Empty file.
9 changes: 9 additions & 0 deletions tests/adapters/mem_fm_runner.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
from sblex.fm.fm_runner import FmRunner, InflectionRow


class MemFmRunner(FmRunner):
def __init__(self, paradigms: dict[str, dict[str, list[InflectionRow]]]) -> None:
self.paradigms = paradigms

def inflection(self, paradigm: str, word: str) -> list[InflectionRow]:
return self.paradigms.get(paradigm, {}).get(word) or []
109 changes: 107 additions & 2 deletions tests/e2e/conftest.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,21 +5,25 @@
from asgi_lifespan import LifespanManager
from fastapi import FastAPI
from httpx import ASGITransport, AsyncClient
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 MatomoSettings
from sblex.saldo_ws.config import FmBinSettings, MatomoSettings
from sblex.saldo_ws.config import Settings as SaldoWsSettings
from sblex.saldo_ws.deps import get_fm_client
from sblex.saldo_ws.deps import get_fm_client, get_fm_runner
from sblex.saldo_ws.server import create_saldo_ws_server
from sblex.telemetry.settings import OTelSettings

from tests.adapters.mem_fm_runner import MemFmRunner


@pytest.fixture(name="webapp")
def fixture_webapp(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",
Expand All @@ -37,7 +41,108 @@ def fixture_webapp(fm_client: AsyncClient) -> FastAPI:
def override_fm_client() -> AsyncClient:
return fm_client

def override_fm_runner() -> FmRunner:
return MemFmRunner(
paradigms={
"vb_vs_dväljas": {
"dväljas": [
{
"word": "dväljes",
"head": "dväljas",
"pos": "vb",
"param": "pres ind s-form",
"inhs": [],
"id": "dväljes_vb",
"p": "vb_vs_dväljas",
"attr": "0",
},
{
"word": "dväljs",
"head": "dväljas",
"pos": "vb",
"param": "pres ind s-form",
"inhs": [],
"id": "dväljes_vb",
"p": "vb_vs_dväljas",
"attr": "0",
},
{
"word": "dvaldes",
"head": "dväljas",
"pos": "vb",
"param": "pret ind s-form",
"inhs": [],
"id": "dväljes_vb",
"p": "vb_vs_dväljas",
"attr": "0",
},
{
"word": "dväljdes",
"head": "dväljas",
"pos": "vb",
"param": "pret ind s-form",
"inhs": [],
"id": "dväljes_vb",
"p": "vb_vs_dväljas",
"attr": "0",
},
{
"word": "dväljes",
"head": "dväljas",
"pos": "vb",
"param": "imper",
"inhs": [],
"id": "dväljes_vb",
"p": "vb_vs_dväljas",
"attr": "0",
},
{
"word": "dväljs",
"head": "dväljas",
"pos": "vb",
"param": "imper",
"inhs": [],
"id": "dväljes_vb",
"p": "vb_vs_dväljas",
"attr": "0",
},
{
"word": "dväljas",
"head": "dväljas",
"pos": "vb",
"param": "inf s-form",
"inhs": [],
"id": "dväljes_vb",
"p": "vb_vs_dväljas",
"attr": "0",
},
{
"word": "dvalts",
"head": "dväljas",
"pos": "vb",
"param": "sup s-form",
"inhs": [],
"id": "dväljes_vb",
"p": "vb_vs_dväljas",
"attr": "0",
},
{
"word": "dvälts",
"head": "dväljas",
"pos": "vb",
"param": "sup s-form",
"inhs": [],
"id": "dväljes_vb",
"p": "vb_vs_dväljas",
"attr": "0",
},
]
}
}
)

webapp.dependency_overrides[get_fm_client] = override_fm_client
webapp.dependency_overrides[get_fm_runner] = override_fm_runner
return webapp


Expand Down
Loading