1
0
Fork 0
forked from Fuji/Fuji

SDK: Move from dataclasses to pydantic, add serialization/deserialization section in docs

This commit is contained in:
Marioneq 2025-02-08 21:43:06 +01:00
parent 09f0cd9415
commit 10061cd0c4
12 changed files with 100 additions and 46 deletions

View file

@ -92,6 +92,70 @@ No możesz pobrać na przykład oceny, możesz to zrobić (gdy jesteś zalogowan
grades = interface.get_grades(<numer semestru>)
```
### Serializacja i wczytywanie danych
SDK używa modeli pydanic, nie są to zwykłe dict'y czy JSON.
#### Dict
`Model -> dict`
```py
model.model_dump()
```
`dict -> model`
```py
model.model_validate()
```
#### Lista dictów
`list[Model] -> list[dict]`
```py
ModelList = pydantic.TypeAdapter(list[Model])
lista_dictow = ModelList.dump_python(lista_modeli)
```
`list[dict] -> list[Model]`
```py
ModelList = pydantic.TypeAdapter(list[Model])
lista_modeli = ModelList.validate_python(lista_dictow)
```
#### JSON (pojedyńczy obiekt)
`Model -> str`
```py
Model.model_dump_json()
```
`str -> model`
```py
Model.model_validate_json()
```
#### JSON (lista)
`list[Model] -> str`
```py
ModelList = pydantic.TypeAdapter(list[Model])
json_ = ModelList.dump_json(lista_modeli)
```
`str -> list[Model]`
```py
ModelList = pydantic.TypeAdapter(list[Model])
lista_modeli = ModelList.validate_json(json_)
```
## Jak dodawać funkcjonalności:
1. Zrób model(e) do danych, nie dawaj zbyt dużo danych, bo pamiętaj, że ma być to uniwersalny model dla wielu dzienników.
@ -122,8 +186,7 @@ class ExamType(Enum):
return ExamType.OTHER
@dataclass
class Exam:
class Exam(BaseModel):
deadline: date
subject: str
type: ExamType

View file

@ -1,15 +1,13 @@
from dataclasses import dataclass
from pydantic import BaseModel
@dataclass
class FsLsQuery:
class FsLsQuery(BaseModel):
wa: str
wtrealm: str
wctx: str
@dataclass
class FsLsResponse:
class FsLsResponse(BaseModel):
wa: str
wresult: str
wctx: str

View file

@ -1,4 +1,3 @@
import dataclasses
import requests
from sdk.src.apis.common.models import FsLsResponse, FsLsQuery
@ -33,9 +32,9 @@ class EfebClient:
method="POST" if prometheus_response else "GET",
url=f"{BASE_LOGIN}/{self._symbol}/{ENDPOINT_LOGIN_FS_LS}",
data=(
dataclasses.asdict(prometheus_response) if prometheus_response else None
dict(prometheus_response) if prometheus_response else None
),
params=dataclasses.asdict(query),
params=dict(query),
)
return parse_fs_ls_response_form(response.text)
@ -43,7 +42,7 @@ class EfebClient:
response = self._session.request(
method="POST" if login_response else "GET",
url=f"{BASE_STUDENT_CE if self._is_ce else BASE_STUDENT}/{self._symbol}/{ENDPOINT_STUDENT_APP}",
data=dataclasses.asdict(login_response) if login_response else None,
data=dict(login_response) if login_response else None,
)
return parse_app_html(response.text)
@ -51,6 +50,6 @@ class EfebClient:
response = self._session.request(
method="POST" if login_response else "GET",
url=f"{BASE_MESSAGES_CE if self._is_ce else BASE_MESSAGES}/{self._symbol}/{ENDPOINT_MESSAGES_APP}",
data=dataclasses.asdict(login_response) if login_response else None,
data=dict(login_response) if login_response else None,
)
return parse_app_html(response.text)

View file

@ -1,9 +1,8 @@
from dataclasses import dataclass
from pydantic import BaseModel
from sdk.src.apis.hebe.signer import generate_key_pair
@dataclass
class Certificate:
class Certificate(BaseModel):
certificate: str
fingerprint: str
private_key: str
@ -12,4 +11,4 @@ class Certificate:
@staticmethod
def generate():
certificate, fingerprint, private_key = generate_key_pair()
return Certificate(certificate, fingerprint, private_key, "X509")
return Certificate(certificate=certificate, fingerprint=fingerprint, private_key=private_key, type="X509")

View file

@ -1,9 +1,7 @@
from dataclasses import dataclass
from datetime import date
from pydantic import BaseModel
@dataclass
class HebePeriod:
class HebePeriod(BaseModel):
id: int
number: int
current: bool
@ -21,8 +19,7 @@ class HebePeriod:
)
@dataclass
class HebeStudent:
class HebeStudent(BaseModel):
id: int
full_name: str
unit_id: int

View file

@ -1,4 +1,3 @@
import dataclasses
import json
from bs4 import BeautifulSoup
import requests
@ -97,7 +96,7 @@ class PrometheusWebClient:
def fs_ls(self, query: FsLsQuery):
response = self._session.get(
f"{PROMETHEUS_WEB_BASE}/{ENDPOINT_FS_LS}",
params=dataclasses.asdict(query),
params=dict(query),
)
if "Logowanie" in response.text:

View file

@ -1,6 +1,7 @@
from datetime import date
from sdk.src.models.exam import Exam
from sdk.src.models.grade import Grade
from sdk.src.models.note import Note
from sdk.src.models.student import Student
@ -22,3 +23,6 @@ class CoreInterface:
def get_exams(from_: date, to: date) -> list[Exam]:
pass
def get_notes() -> list[Note]:
pass

View file

@ -1,12 +1,11 @@
from dataclasses import dataclass
from pydantic import BaseModel
from sdk.src.apis.hebe import HebeCertificate
from sdk.src.apis.hebe.student import HebeStudent
from sdk.src.interfaces.prometheus.utils import get_context_periods_from_hebe_periods
@dataclass
class PrometheusStudentContext:
class PrometheusStudentContext(BaseModel):
student_id: int
unit_id: int
constituent_id: int
@ -32,16 +31,14 @@ class PrometheusStudentContext:
)
@dataclass
class PrometheusWebCredentials:
class PrometheusWebCredentials(BaseModel):
username: str
password: str
@dataclass
class PrometheusAuthContext:
class PrometheusAuthContext(BaseModel):
prometheus_web_credentials: PrometheusWebCredentials
symbols: list[str] | None = None
hebe_certificate: HebeCertificate | None = None
prometheus_web_cookies: dict[str, str] | None = None
efeb_web_cookies: dict[str, str | None] | None = None
efeb_web_cookies: dict[str, dict[str, str] | None] | None = None

View file

@ -1,7 +1,8 @@
from dataclasses import dataclass
from datetime import date, datetime
from enum import Enum
from pydantic import BaseModel
class ExamType(Enum):
TEST = 0
@ -22,8 +23,7 @@ class ExamType(Enum):
return ExamType.OTHER
@dataclass
class Exam:
class Exam(BaseModel):
deadline: date
subject: str
type: ExamType

View file

@ -1,9 +1,9 @@
from dataclasses import dataclass
from datetime import datetime
from pydantic import BaseModel
@dataclass
class Grade:
class Grade(BaseModel):
value: str
is_point: bool
point_numerator: int

View file

@ -1,9 +1,8 @@
from dataclasses import dataclass
from datetime import datetime
from pydantic import BaseModel
@dataclass
class Note:
class Note(BaseModel):
name: str | None
content: str
points: str | None

View file

@ -1,12 +1,12 @@
from dataclasses import dataclass
from datetime import date
from typing import Generic, TypeVar
from pydantic import BaseModel
from sdk.src.apis.hebe.student import HebePeriod, HebeStudent
@dataclass
class Period:
class Period(BaseModel):
id: int
number: int
current: bool
@ -27,8 +27,7 @@ class Period:
T = TypeVar("T")
@dataclass
class Student(Generic[T]):
class Student(BaseModel, Generic[T]):
full_name: str
is_parent: bool
class_name: str