Skip to content

Commit 33426f6

Browse files
authored
Rework the results a little bit to account for Mauros missing component. (#24)
1 parent 8841d81 commit 33426f6

File tree

8 files changed

+237
-159
lines changed

8 files changed

+237
-159
lines changed

src/smartschool/__init__.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,7 @@
1919
)
2020
from .periods import Periods
2121
from .planner import ApplicableAssignmentTypes, PlannedElements
22-
from .results import ResultDetail, Results
22+
from .results import Result, Results
2323
from .session import Smartschool
2424
from .student_support import StudentSupportLinks
2525

@@ -50,7 +50,7 @@
5050
"PathCredentials",
5151
"Periods",
5252
"PlannedElements",
53-
"ResultDetail",
53+
"Result",
5454
"Results",
5555
"SmartSchoolAuthenticationError",
5656
"SmartSchoolDownloadError",

src/smartschool/objects.py

Lines changed: 5 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -156,22 +156,25 @@ class FeedbackFull:
156156

157157

158158
@dataclass
159-
class _Result:
159+
class Result:
160160
identifier: String
161161
type: Literal["normal"]
162162
name: String
163163
graphic: ResultGraphic
164164
date: DateTime
165165

166166
gradebookOwner: Teacher
167-
component: Component
167+
component: Component | None
168168
courses: list[Course]
169169
period: Period
170170
feedback: list[Feedback]
171171
feedbacks: list[FeedbackFull]
172172
availabilityDate: DateTime
173173
isPublished: bool
174174
doesCount: bool
175+
deleted: bool = False
176+
177+
details: ResultDetails | None = None
175178

176179

177180
@dataclass
@@ -183,17 +186,6 @@ class ResultDetails:
183186
class_: Class_ = Field(validation_alias=AliasChoices("class", "class_"))
184187

185188

186-
@dataclass
187-
class ResultWithoutDetails(_Result):
188-
deleted: bool = False
189-
190-
191-
@dataclass
192-
class ResultWithDetails(_Result):
193-
details: ResultDetails
194-
deleted: bool = False
195-
196-
197189
@dataclass
198190
class CourseCondensed:
199191
name: String

src/smartschool/results.py

Lines changed: 25 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -2,18 +2,33 @@
22
from dataclasses import dataclass
33
from itertools import count
44

5-
from .exceptions import SmartSchoolDownloadError
6-
from .objects import ResultWithDetails, ResultWithoutDetails
5+
from . import objects
76

8-
__all__ = ["ResultDetail", "Results"]
7+
__all__ = ["Results"]
98

109
from .session import SessionMixin
1110

1211
RESULTS_PER_PAGE = 50
1312

1413

1514
@dataclass
16-
class Results(SessionMixin, Iterable[ResultWithoutDetails]):
15+
class Result(objects.Result, SessionMixin):
16+
def __getattribute__(self, name: str):
17+
attr = super().__getattribute__(name)
18+
if name != "details":
19+
return attr
20+
21+
if attr is not None:
22+
return attr
23+
24+
data = self.session.json(f"/results/api/v1/evaluations/{self.identifier}")
25+
details_obj = objects.Result(**data)
26+
super().__setattr__("details", details_obj.details)
27+
return details_obj.details
28+
29+
30+
@dataclass
31+
class Results(SessionMixin, Iterable[Result]):
1732
"""
1833
Interfaces with the evaluations of smartschool.
1934
@@ -27,28 +42,12 @@ class Results(SessionMixin, Iterable[ResultWithoutDetails]):
2742
2843
"""
2944

30-
def __iter__(self) -> Iterator[ResultWithoutDetails]:
45+
def __iter__(self) -> Iterator[Result]:
3146
for page_nr in count(start=1): # pragma: no branch
32-
downloaded_webpage = self.session.get(f"/results/api/v1/evaluations/?pageNumber={page_nr}&itemsOnPage={RESULTS_PER_PAGE}")
33-
if not downloaded_webpage or not downloaded_webpage.content:
34-
raise SmartSchoolDownloadError("No JSON was returned for the results?!")
35-
36-
json = downloaded_webpage.json()
37-
for result in json:
38-
yield ResultWithoutDetails(**result)
47+
data = self.session.json(f"/results/api/v1/evaluations/?pageNumber={page_nr}&itemsOnPage={RESULTS_PER_PAGE}")
48+
for result in data:
49+
pyd = objects.Result(**result)
50+
yield Result(session=self.session, **pyd.__dict__)
3951

40-
if len(json) < RESULTS_PER_PAGE:
52+
if len(data) < RESULTS_PER_PAGE:
4153
break
42-
43-
44-
@dataclass
45-
class ResultDetail(SessionMixin):
46-
result_id: str
47-
48-
def get(self) -> ResultWithDetails:
49-
downloaded_webpage = self.session.get(f"/results/api/v1/evaluations/{self.result_id}")
50-
if not downloaded_webpage or not downloaded_webpage.content:
51-
raise SmartSchoolDownloadError("No JSON was returned for the details?!")
52-
53-
json = downloaded_webpage.json()
54-
return ResultWithDetails(**json)

tests/conftest.py

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -120,7 +120,11 @@ def get_filename(req) -> Path:
120120
def binary_callback(req, _) -> bytes:
121121
filename = get_filename(req)
122122

123-
logger.debug(f"[REQUESTMOCK-BIN] {filename.exists()=} -> {filename}")
123+
if req.text:
124+
logger.debug(f"[REQUESTMOCK] {req} [{req.text}]")
125+
else:
126+
logger.debug(f"[REQUESTMOCK] {req}")
127+
logger.debug(f"[REQUESTMOCK] ==> {filename} (exists: {filename.exists()})")
124128
if filename.exists():
125129
return filename.read_bytes()
126130

Lines changed: 83 additions & 80 deletions
Original file line numberDiff line numberDiff line change
@@ -1,41 +1,16 @@
1-
[{
2-
"identifier": "49_10880_0_normal_769824",
3-
"type": "normal",
4-
"name": "Repetitie hoofdstuk 1",
5-
"graphic": {
6-
"type": "percentage",
7-
"color": "green",
8-
"value": 75,
9-
"description": "13,5/18"
10-
},
11-
"date": "2023-11-10T00:00:00+01:00",
12-
"gradebookOwner": {
13-
"id": "49_10844_0",
14-
"pictureHash": "initials_GS",
15-
"pictureUrl": "https://userpicture20.smartschool.be/User/Userimage/hashimage/hash/initials_GS/plain/1/res/128",
16-
"description": {
17-
"startingWithFirstName": "",
18-
"startingWithLastName": ""
19-
},
20-
"name": {
21-
"startingWithFirstName": "Gert Segers",
22-
"startingWithLastName": "Segers Gert"
23-
},
24-
"sort": "segers-gert"
25-
},
26-
"component": {
27-
"id": 7,
28-
"name": "dagelijks werk",
29-
"abbreviation": "DW"
30-
},
31-
"courses": [{
32-
"id": 1227,
33-
"name": "Geschiedenis",
1+
[
2+
{
3+
"identifier": "49_10880_0_normal_769824",
4+
"type": "normal",
5+
"name": "Repetitie hoofdstuk 1",
346
"graphic": {
35-
"type": "icon",
36-
"value": "knight2"
7+
"type": "percentage",
8+
"color": "green",
9+
"value": 75,
10+
"description": "13,5/18"
3711
},
38-
"teachers": [{
12+
"date": "2023-11-10T00:00:00+01:00",
13+
"gradebookOwner": {
3914
"id": "49_10844_0",
4015
"pictureHash": "initials_GS",
4116
"pictureUrl": "https://userpicture20.smartschool.be/User/Userimage/hashimage/hash/initials_GS/plain/1/res/128",
@@ -48,52 +23,80 @@
4823
"startingWithLastName": "Segers Gert"
4924
},
5025
"sort": "segers-gert"
51-
}
52-
],
53-
"class": {
54-
"identifier": "49_3467",
55-
"id": 3467,
56-
"platformId": 49,
57-
"name": "3ENW",
58-
"type": "K",
59-
"icon": "briefcase"
6026
},
61-
"skoreClassId": 6104,
62-
"parentCourseId": null,
63-
"skoreWorkYear": {
64-
"id": 32,
65-
"dateRange": {
66-
"start": "2023-09-01T00:00:00+02:00",
67-
"end": "2024-08-31T00:00:00+02:00"
68-
}
69-
}
70-
}
71-
],
72-
"period": {
73-
"id": 4056,
74-
"name": "25 oktober - 19 december",
75-
"icon": "cal_purple_generic_week",
76-
"class": {
77-
"identifier": "49_3467",
78-
"id": 3467,
79-
"platformId": 49,
80-
"name": "3ENW",
81-
"type": "K",
82-
"icon": "briefcase"
27+
"component": {
28+
"id": 7,
29+
"name": "dagelijks werk",
30+
"abbreviation": "DW"
8331
},
84-
"skoreWorkYear": {
85-
"id": 32,
86-
"dateRange": {
87-
"start": "2023-09-01T00:00:00+02:00",
88-
"end": "2024-08-31T00:00:00+02:00"
32+
"courses": [
33+
{
34+
"id": 1227,
35+
"name": "Geschiedenis",
36+
"graphic": {
37+
"type": "icon",
38+
"value": "knight2"
39+
},
40+
"teachers": [
41+
{
42+
"id": "49_10844_0",
43+
"pictureHash": "initials_GS",
44+
"pictureUrl": "https://userpicture20.smartschool.be/User/Userimage/hashimage/hash/initials_GS/plain/1/res/128",
45+
"description": {
46+
"startingWithFirstName": "",
47+
"startingWithLastName": ""
48+
},
49+
"name": {
50+
"startingWithFirstName": "Gert Segers",
51+
"startingWithLastName": "Segers Gert"
52+
},
53+
"sort": "segers-gert"
54+
}
55+
],
56+
"class": {
57+
"identifier": "49_3467",
58+
"id": 3467,
59+
"platformId": 49,
60+
"name": "3ENW",
61+
"type": "K",
62+
"icon": "briefcase"
63+
},
64+
"skoreClassId": 6104,
65+
"parentCourseId": null,
66+
"skoreWorkYear": {
67+
"id": 32,
68+
"dateRange": {
69+
"start": "2023-09-01T00:00:00+02:00",
70+
"end": "2024-08-31T00:00:00+02:00"
71+
}
72+
}
8973
}
74+
],
75+
"period": {
76+
"id": 4056,
77+
"name": "25 oktober - 19 december",
78+
"icon": "cal_purple_generic_week",
79+
"class": {
80+
"identifier": "49_3467",
81+
"id": 3467,
82+
"platformId": 49,
83+
"name": "3ENW",
84+
"type": "K",
85+
"icon": "briefcase"
86+
},
87+
"skoreWorkYear": {
88+
"id": 32,
89+
"dateRange": {
90+
"start": "2023-09-01T00:00:00+02:00",
91+
"end": "2024-08-31T00:00:00+02:00"
92+
}
93+
},
94+
"isActive": true
9095
},
91-
"isActive": true
92-
},
93-
"feedback": [],
94-
"feedbacks": [],
95-
"availabilityDate": "2023-11-14T18:00:00+01:00",
96-
"isPublished": true,
97-
"doesCount": true
98-
}
96+
"feedback": [],
97+
"feedbacks": [],
98+
"availabilityDate": "2023-11-14T18:00:00+01:00",
99+
"isPublished": true,
100+
"doesCount": true
101+
}
99102
]

0 commit comments

Comments
 (0)