SDK: Move from dataclasses to pydantic, add serialization/deserialization section in docs
This commit is contained in:
parent
09f0cd9415
commit
10061cd0c4
12 changed files with 100 additions and 46 deletions
|
@ -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>)
|
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:
|
## 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.
|
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
|
return ExamType.OTHER
|
||||||
|
|
||||||
|
|
||||||
@dataclass
|
class Exam(BaseModel):
|
||||||
class Exam:
|
|
||||||
deadline: date
|
deadline: date
|
||||||
subject: str
|
subject: str
|
||||||
type: ExamType
|
type: ExamType
|
||||||
|
|
|
@ -1,15 +1,13 @@
|
||||||
from dataclasses import dataclass
|
from pydantic import BaseModel
|
||||||
|
|
||||||
|
|
||||||
@dataclass
|
class FsLsQuery(BaseModel):
|
||||||
class FsLsQuery:
|
|
||||||
wa: str
|
wa: str
|
||||||
wtrealm: str
|
wtrealm: str
|
||||||
wctx: str
|
wctx: str
|
||||||
|
|
||||||
|
|
||||||
@dataclass
|
class FsLsResponse(BaseModel):
|
||||||
class FsLsResponse:
|
|
||||||
wa: str
|
wa: str
|
||||||
wresult: str
|
wresult: str
|
||||||
wctx: str
|
wctx: str
|
||||||
|
|
|
@ -1,4 +1,3 @@
|
||||||
import dataclasses
|
|
||||||
import requests
|
import requests
|
||||||
|
|
||||||
from sdk.src.apis.common.models import FsLsResponse, FsLsQuery
|
from sdk.src.apis.common.models import FsLsResponse, FsLsQuery
|
||||||
|
@ -33,9 +32,9 @@ class EfebClient:
|
||||||
method="POST" if prometheus_response else "GET",
|
method="POST" if prometheus_response else "GET",
|
||||||
url=f"{BASE_LOGIN}/{self._symbol}/{ENDPOINT_LOGIN_FS_LS}",
|
url=f"{BASE_LOGIN}/{self._symbol}/{ENDPOINT_LOGIN_FS_LS}",
|
||||||
data=(
|
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)
|
return parse_fs_ls_response_form(response.text)
|
||||||
|
|
||||||
|
@ -43,7 +42,7 @@ class EfebClient:
|
||||||
response = self._session.request(
|
response = self._session.request(
|
||||||
method="POST" if login_response else "GET",
|
method="POST" if login_response else "GET",
|
||||||
url=f"{BASE_STUDENT_CE if self._is_ce else BASE_STUDENT}/{self._symbol}/{ENDPOINT_STUDENT_APP}",
|
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)
|
return parse_app_html(response.text)
|
||||||
|
|
||||||
|
@ -51,6 +50,6 @@ class EfebClient:
|
||||||
response = self._session.request(
|
response = self._session.request(
|
||||||
method="POST" if login_response else "GET",
|
method="POST" if login_response else "GET",
|
||||||
url=f"{BASE_MESSAGES_CE if self._is_ce else BASE_MESSAGES}/{self._symbol}/{ENDPOINT_MESSAGES_APP}",
|
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)
|
return parse_app_html(response.text)
|
||||||
|
|
|
@ -1,9 +1,8 @@
|
||||||
from dataclasses import dataclass
|
from pydantic import BaseModel
|
||||||
from sdk.src.apis.hebe.signer import generate_key_pair
|
from sdk.src.apis.hebe.signer import generate_key_pair
|
||||||
|
|
||||||
|
|
||||||
@dataclass
|
class Certificate(BaseModel):
|
||||||
class Certificate:
|
|
||||||
certificate: str
|
certificate: str
|
||||||
fingerprint: str
|
fingerprint: str
|
||||||
private_key: str
|
private_key: str
|
||||||
|
@ -12,4 +11,4 @@ class Certificate:
|
||||||
@staticmethod
|
@staticmethod
|
||||||
def generate():
|
def generate():
|
||||||
certificate, fingerprint, private_key = generate_key_pair()
|
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")
|
||||||
|
|
|
@ -1,9 +1,7 @@
|
||||||
from dataclasses import dataclass
|
|
||||||
from datetime import date
|
from datetime import date
|
||||||
|
from pydantic import BaseModel
|
||||||
|
|
||||||
|
class HebePeriod(BaseModel):
|
||||||
@dataclass
|
|
||||||
class HebePeriod:
|
|
||||||
id: int
|
id: int
|
||||||
number: int
|
number: int
|
||||||
current: bool
|
current: bool
|
||||||
|
@ -21,8 +19,7 @@ class HebePeriod:
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
@dataclass
|
class HebeStudent(BaseModel):
|
||||||
class HebeStudent:
|
|
||||||
id: int
|
id: int
|
||||||
full_name: str
|
full_name: str
|
||||||
unit_id: int
|
unit_id: int
|
||||||
|
|
|
@ -1,4 +1,3 @@
|
||||||
import dataclasses
|
|
||||||
import json
|
import json
|
||||||
from bs4 import BeautifulSoup
|
from bs4 import BeautifulSoup
|
||||||
import requests
|
import requests
|
||||||
|
@ -97,7 +96,7 @@ class PrometheusWebClient:
|
||||||
def fs_ls(self, query: FsLsQuery):
|
def fs_ls(self, query: FsLsQuery):
|
||||||
response = self._session.get(
|
response = self._session.get(
|
||||||
f"{PROMETHEUS_WEB_BASE}/{ENDPOINT_FS_LS}",
|
f"{PROMETHEUS_WEB_BASE}/{ENDPOINT_FS_LS}",
|
||||||
params=dataclasses.asdict(query),
|
params=dict(query),
|
||||||
)
|
)
|
||||||
|
|
||||||
if "Logowanie" in response.text:
|
if "Logowanie" in response.text:
|
||||||
|
|
|
@ -1,6 +1,7 @@
|
||||||
from datetime import date
|
from datetime import date
|
||||||
from sdk.src.models.exam import Exam
|
from sdk.src.models.exam import Exam
|
||||||
from sdk.src.models.grade import Grade
|
from sdk.src.models.grade import Grade
|
||||||
|
from sdk.src.models.note import Note
|
||||||
from sdk.src.models.student import Student
|
from sdk.src.models.student import Student
|
||||||
|
|
||||||
|
|
||||||
|
@ -22,3 +23,6 @@ class CoreInterface:
|
||||||
|
|
||||||
def get_exams(from_: date, to: date) -> list[Exam]:
|
def get_exams(from_: date, to: date) -> list[Exam]:
|
||||||
pass
|
pass
|
||||||
|
|
||||||
|
def get_notes() -> list[Note]:
|
||||||
|
pass
|
||||||
|
|
|
@ -1,12 +1,11 @@
|
||||||
from dataclasses import dataclass
|
from pydantic import BaseModel
|
||||||
|
|
||||||
from sdk.src.apis.hebe import HebeCertificate
|
from sdk.src.apis.hebe import HebeCertificate
|
||||||
from sdk.src.apis.hebe.student import HebeStudent
|
from sdk.src.apis.hebe.student import HebeStudent
|
||||||
from sdk.src.interfaces.prometheus.utils import get_context_periods_from_hebe_periods
|
from sdk.src.interfaces.prometheus.utils import get_context_periods_from_hebe_periods
|
||||||
|
|
||||||
|
|
||||||
@dataclass
|
class PrometheusStudentContext(BaseModel):
|
||||||
class PrometheusStudentContext:
|
|
||||||
student_id: int
|
student_id: int
|
||||||
unit_id: int
|
unit_id: int
|
||||||
constituent_id: int
|
constituent_id: int
|
||||||
|
@ -32,16 +31,14 @@ class PrometheusStudentContext:
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
@dataclass
|
class PrometheusWebCredentials(BaseModel):
|
||||||
class PrometheusWebCredentials:
|
|
||||||
username: str
|
username: str
|
||||||
password: str
|
password: str
|
||||||
|
|
||||||
|
|
||||||
@dataclass
|
class PrometheusAuthContext(BaseModel):
|
||||||
class PrometheusAuthContext:
|
|
||||||
prometheus_web_credentials: PrometheusWebCredentials
|
prometheus_web_credentials: PrometheusWebCredentials
|
||||||
symbols: list[str] | None = None
|
symbols: list[str] | None = None
|
||||||
hebe_certificate: HebeCertificate | None = None
|
hebe_certificate: HebeCertificate | None = None
|
||||||
prometheus_web_cookies: dict[str, str] | 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
|
||||||
|
|
|
@ -1,7 +1,8 @@
|
||||||
from dataclasses import dataclass
|
|
||||||
from datetime import date, datetime
|
from datetime import date, datetime
|
||||||
from enum import Enum
|
from enum import Enum
|
||||||
|
|
||||||
|
from pydantic import BaseModel
|
||||||
|
|
||||||
|
|
||||||
class ExamType(Enum):
|
class ExamType(Enum):
|
||||||
TEST = 0
|
TEST = 0
|
||||||
|
@ -22,8 +23,7 @@ class ExamType(Enum):
|
||||||
return ExamType.OTHER
|
return ExamType.OTHER
|
||||||
|
|
||||||
|
|
||||||
@dataclass
|
class Exam(BaseModel):
|
||||||
class Exam:
|
|
||||||
deadline: date
|
deadline: date
|
||||||
subject: str
|
subject: str
|
||||||
type: ExamType
|
type: ExamType
|
||||||
|
|
|
@ -1,9 +1,9 @@
|
||||||
from dataclasses import dataclass
|
|
||||||
from datetime import datetime
|
from datetime import datetime
|
||||||
|
|
||||||
|
from pydantic import BaseModel
|
||||||
|
|
||||||
@dataclass
|
|
||||||
class Grade:
|
class Grade(BaseModel):
|
||||||
value: str
|
value: str
|
||||||
is_point: bool
|
is_point: bool
|
||||||
point_numerator: int
|
point_numerator: int
|
||||||
|
|
|
@ -1,9 +1,8 @@
|
||||||
from dataclasses import dataclass
|
|
||||||
from datetime import datetime
|
from datetime import datetime
|
||||||
|
from pydantic import BaseModel
|
||||||
|
|
||||||
|
|
||||||
@dataclass
|
class Note(BaseModel):
|
||||||
class Note:
|
|
||||||
name: str | None
|
name: str | None
|
||||||
content: str
|
content: str
|
||||||
points: str | None
|
points: str | None
|
||||||
|
|
|
@ -1,12 +1,12 @@
|
||||||
from dataclasses import dataclass
|
|
||||||
from datetime import date
|
from datetime import date
|
||||||
from typing import Generic, TypeVar
|
from typing import Generic, TypeVar
|
||||||
|
|
||||||
|
from pydantic import BaseModel
|
||||||
|
|
||||||
from sdk.src.apis.hebe.student import HebePeriod, HebeStudent
|
from sdk.src.apis.hebe.student import HebePeriod, HebeStudent
|
||||||
|
|
||||||
|
|
||||||
@dataclass
|
class Period(BaseModel):
|
||||||
class Period:
|
|
||||||
id: int
|
id: int
|
||||||
number: int
|
number: int
|
||||||
current: bool
|
current: bool
|
||||||
|
@ -27,8 +27,7 @@ class Period:
|
||||||
T = TypeVar("T")
|
T = TypeVar("T")
|
||||||
|
|
||||||
|
|
||||||
@dataclass
|
class Student(BaseModel, Generic[T]):
|
||||||
class Student(Generic[T]):
|
|
||||||
full_name: str
|
full_name: str
|
||||||
is_parent: bool
|
is_parent: bool
|
||||||
class_name: str
|
class_name: str
|
||||||
|
|
Loading…
Add table
Reference in a new issue