schoolmospy 0.2.1__py3-none-any.whl → 0.2.2__py3-none-any.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
schoolmospy/__init__.py CHANGED
@@ -1,2 +1,4 @@
1
- from schoolmospy.core.student_client import StudentClient
2
- from schoolmospy.core.basic_client import BasicClient
1
+ from schoolmospy.core.basic_client import BasicClient as BasicClient
2
+ from schoolmospy.core.student_client import StudentClient as StudentClient
3
+
4
+ __all__ = ["BasicClient", "StudentClient"]
@@ -1,18 +1,20 @@
1
+ from typing import Any
2
+
1
3
  import httpx
2
- from typing import Any, Optional, Type
3
4
  from pydantic import BaseModel
4
- from schoolmospy.utils.exceptions import APIError, AuthError, NotFoundError, ServerError, HTTPError
5
+
6
+ from schoolmospy.utils.exceptions import APIError, AuthError, HTTPError, NotFoundError, ServerError
5
7
 
6
8
 
7
9
  class BasicClient:
8
10
  def __init__(
9
11
  self,
10
12
  base_url: str,
11
- token: Optional[str] = None,
12
- profile_id: Optional[int] = None,
13
+ token: str | None = None,
14
+ profile_id: int | None = None,
13
15
  profile_type: str = "student",
14
16
  timeout: float = 15.0,
15
- ):
17
+ ) -> None:
16
18
  self.base_url = base_url.rstrip("/")
17
19
  self.token = token
18
20
  self.profile_id = profile_id
@@ -33,10 +35,14 @@ class BasicClient:
33
35
  headers["Profile-Id"] = str(self.profile_id)
34
36
  if self.profile_type:
35
37
  headers["Profile-Type"] = self.profile_type
36
- headers["X-Mes-Role"] = self.profile_type
38
+ headers["X-Mes-Role"] = self.profile_type
37
39
  return headers
38
40
 
39
- async def _handle_response(self, response: httpx.Response, response_model: Optional[Type[BaseModel]] = None):
41
+ async def _handle_response(
42
+ self,
43
+ response: httpx.Response,
44
+ response_model: type[BaseModel] | None = None,
45
+ ) -> Any:
40
46
  if response.is_success:
41
47
  if response_model:
42
48
  return response_model.model_validate(response.json())
@@ -47,14 +53,18 @@ class BasicClient:
47
53
 
48
54
  if status == 401:
49
55
  raise AuthError("Unauthorized or invalid token", status, text)
50
- elif status == 404:
56
+ if status == 404:
51
57
  raise NotFoundError("Resource not found", status, text)
52
- elif status >= 500:
58
+ if status >= 500:
53
59
  raise ServerError("Server error", status, text)
54
- else:
55
- raise HTTPError(f"Unexpected response ({status})", status, text)
60
+ raise HTTPError(f"Unexpected response ({status})", status, text)
56
61
 
57
- async def get(self, endpoint: str, response_model: Optional[Type[BaseModel]] = None, **kwargs: Any):
62
+ async def get(
63
+ self,
64
+ endpoint: str,
65
+ response_model: type[BaseModel] | None = None,
66
+ **kwargs: Any,
67
+ ) -> Any:
58
68
  url = f"{self.base_url}/{endpoint.lstrip('/')}"
59
69
  async with httpx.AsyncClient(headers=self.headers, timeout=self.timeout) as client:
60
70
  try:
@@ -63,7 +73,13 @@ class BasicClient:
63
73
  raise APIError(f"Request failed: {e}") from e
64
74
  return await self._handle_response(resp, response_model)
65
75
 
66
- async def post(self, endpoint: str, data: Any = None, response_model: Optional[Type[BaseModel]] = None, **kwargs: Any):
76
+ async def post(
77
+ self,
78
+ endpoint: str,
79
+ data: Any = None,
80
+ response_model: type[BaseModel] | None = None,
81
+ **kwargs: Any,
82
+ ) -> Any:
67
83
  url = f"{self.base_url}/{endpoint.lstrip('/')}"
68
84
  async with httpx.AsyncClient(headers=self.headers, timeout=self.timeout) as client:
69
85
  try:
@@ -1,10 +1,11 @@
1
1
  from datetime import datetime
2
+
2
3
  from schoolmospy.core.basic_client import BasicClient
3
4
  from schoolmospy.models.events import Events
4
5
 
5
6
 
6
7
  class EventClient:
7
- def __init__(self, client: BasicClient):
8
+ def __init__(self, client: BasicClient) -> None:
8
9
  """
9
10
  Initialization the EventClient instance.
10
11
 
@@ -14,7 +15,7 @@ class EventClient:
14
15
  """
15
16
  self.client = client
16
17
 
17
- async def get(self, from_date: datetime, to_date: datetime, contingent_guid: str = None) -> Events:
18
+ async def get(self, from_date: datetime, to_date: datetime, contingent_guid: str) -> Events:
18
19
  """
19
20
  Method for getting events done within a certain period of time
20
21
 
@@ -36,7 +37,7 @@ class EventClient:
36
37
  from schoolmospy.clients.student_client import StudentClient
37
38
 
38
39
  client = StudentClient(token="YOUR_TOKEN", profile_id=17234613)
39
-
40
+
40
41
  me = await client.get_me()
41
42
 
42
43
  events = await client.events.get(
@@ -48,7 +49,6 @@ class EventClient:
48
49
  ```
49
50
  """
50
51
 
51
-
52
52
  return await self.client.get(
53
53
  "/api/eventcalendar/v1/api/events",
54
54
  Events,
@@ -57,6 +57,6 @@ class EventClient:
57
57
  "to": to_date.strftime("%Y-%m-%d"),
58
58
  "person_ids": contingent_guid,
59
59
  "expand": "marks,homework,absence_reason_id,health_status,nonattendance_reason_id",
60
- "source_types": "PLAN,AE,EC,EVENTS,AFISHA,ORGANIZER,OLYMPIAD,PROF"
61
- }
60
+ "source_types": "PLAN,AE,EC,EVENTS,AFISHA,ORGANIZER,OLYMPIAD,PROF",
61
+ },
62
62
  )
@@ -1,10 +1,11 @@
1
1
  from datetime import datetime
2
+
2
3
  from schoolmospy.core.basic_client import BasicClient
3
4
  from schoolmospy.models.homeworks import Homeworks
4
5
 
5
6
 
6
7
  class HomeworkClient:
7
- def __init__(self, client: BasicClient):
8
+ def __init__(self, client: BasicClient) -> None:
8
9
  """
9
10
  Initialization the HomeworkClient instance.
10
11
 
@@ -43,13 +44,12 @@ class HomeworkClient:
43
44
  ```
44
45
  """
45
46
 
46
-
47
47
  return await self.client.get(
48
48
  "/api/family/web/v1/homeworks",
49
49
  Homeworks,
50
50
  params={
51
51
  "from": from_date.strftime("%Y-%m-%d"),
52
52
  "to": to_date.strftime("%Y-%m-%d"),
53
- "student_id": self.client.profile_id
54
- }
53
+ "student_id": self.client.profile_id,
54
+ },
55
55
  )
@@ -1,10 +1,11 @@
1
1
  from datetime import datetime
2
+
2
3
  from schoolmospy.core.basic_client import BasicClient
3
4
  from schoolmospy.models.marks import Marks
4
5
 
5
6
 
6
7
  class MarksClient:
7
- def __init__(self, client: BasicClient):
8
+ def __init__(self, client: BasicClient) -> None:
8
9
  self.client = client
9
10
 
10
11
  async def get(self, from_date: datetime, to_date: datetime) -> Marks:
@@ -41,6 +42,6 @@ class MarksClient:
41
42
  params={
42
43
  "from": from_date.strftime("%Y-%m-%d"),
43
44
  "to": to_date.strftime("%Y-%m-%d"),
44
- "student_id": self.client.profile_id
45
- }
45
+ "student_id": self.client.profile_id,
46
+ },
46
47
  )
@@ -1,25 +1,25 @@
1
- from typing import Optional
2
1
  from schoolmospy.core.basic_client import BasicClient
3
- from schoolmospy.models.profile import Profile
4
- from schoolmospy.models.userinfo import Userinfo
2
+ from schoolmospy.core.events_client import EventClient
5
3
  from schoolmospy.core.homeworks_client import HomeworkClient
6
4
  from schoolmospy.core.marks_client import MarksClient
7
- from schoolmospy.core.events_client import EventClient
5
+ from schoolmospy.models.profile import Profile
6
+ from schoolmospy.models.userinfo import Userinfo
8
7
 
9
8
 
10
9
  class StudentClient(BasicClient):
11
- def __init__(self,
12
- base_url: str = "https://school.mos.ru",
13
- token: Optional[str] = None,
14
- profile_id: Optional[int] = None,
15
- profile_type: str = "student",
16
- timeout: float = 15.0):
10
+ def __init__(
11
+ self,
12
+ base_url: str = "https://school.mos.ru",
13
+ token: str | None = None,
14
+ profile_id: int | None = None,
15
+ profile_type: str = "student",
16
+ timeout: float = 15.0,
17
+ ) -> None:
17
18
  super().__init__(base_url, token, profile_id, profile_type, timeout)
18
19
  self.homeworks = HomeworkClient(self)
19
20
  self.marks = MarksClient(self)
20
21
  self.events = EventClient(self)
21
22
 
22
-
23
23
  async def get_me(self) -> Profile:
24
24
  """
25
25
  Get the current user's profile information.
@@ -39,7 +39,4 @@ class StudentClient(BasicClient):
39
39
  Returns:
40
40
  Userinfo: Object with basic user information
41
41
  """
42
- return await self.get(
43
- "/v1/oauth/userinfo",
44
- Userinfo
45
- )
42
+ return await self.get("/v1/oauth/userinfo", Userinfo)
@@ -1,6 +1,6 @@
1
1
  from __future__ import annotations
2
2
 
3
- from typing import Any, List, Optional
3
+ from typing import Any
4
4
 
5
5
  from pydantic import BaseModel
6
6
 
@@ -11,27 +11,27 @@ class EventItem(BaseModel):
11
11
  source: str
12
12
  start_at: str
13
13
  finish_at: str
14
- cancelled: Optional[bool] = None
15
- lesson_type: Optional[str] = None
16
- course_lesson_type: Optional[Any] = None
17
- lesson_form: Optional[Any] = None
18
- replaced: Optional[bool] = None
19
- room_name: Optional[str]
20
- room_number: Optional[str]
21
- subject_id: Optional[int] = None
14
+ cancelled: bool | None = None
15
+ lesson_type: str | None = None
16
+ course_lesson_type: Any | None = None
17
+ lesson_form: Any | None = None
18
+ replaced: bool | None = None
19
+ room_name: str | None
20
+ room_number: str | None
21
+ subject_id: int | None = None
22
22
  subject_name: str
23
- link_to_join: Optional[Any] = None
23
+ link_to_join: Any | None = None
24
24
  health_status: Any
25
25
  absence_reason_id: Any
26
26
  nonattendance_reason_id: Any
27
- homework: Optional[Any] = None
28
- marks: Optional[Any] = None
27
+ homework: Any | None = None
28
+ marks: Any | None = None
29
29
  is_missed_lesson: bool
30
- esz_field_id: Optional[int] = None
31
- lesson_theme: Optional[Any] = None
30
+ esz_field_id: int | None = None
31
+ lesson_theme: Any | None = None
32
32
 
33
33
 
34
34
  class Events(BaseModel):
35
35
  total_count: int
36
- response: List[EventItem]
37
- errors: Any
36
+ response: list[EventItem]
37
+ errors: Any
@@ -1,6 +1,6 @@
1
1
  from __future__ import annotations
2
2
 
3
- from typing import Any, List, Optional
3
+ from typing import Any
4
4
 
5
5
  from pydantic import BaseModel
6
6
 
@@ -11,12 +11,12 @@ class Url(BaseModel):
11
11
 
12
12
 
13
13
  class Material(BaseModel):
14
- uuid: Optional[str]
14
+ uuid: str | None
15
15
  type: str
16
- selected_mode: Optional[str]
16
+ selected_mode: str | None
17
17
  type_name: str
18
- id: Optional[int]
19
- urls: List[Url]
18
+ id: int | None
19
+ urls: list[Url]
20
20
  description: Any
21
21
  content_type: Any
22
22
  title: str
@@ -27,11 +27,11 @@ class Material(BaseModel):
27
27
  class HomeworkItem(BaseModel):
28
28
  type: str
29
29
  description: str
30
- comments: List
31
- materials: List[Material]
30
+ comments: list
31
+ materials: list[Material]
32
32
  homework: str
33
33
  homework_entry_student_id: int
34
- attachments: List
34
+ attachments: list
35
35
  subject_id: int
36
36
  group_id: int
37
37
  date: str
@@ -49,4 +49,4 @@ class HomeworkItem(BaseModel):
49
49
 
50
50
 
51
51
  class Homeworks(BaseModel):
52
- payload: List[HomeworkItem]
52
+ payload: list[HomeworkItem]
@@ -1,6 +1,6 @@
1
1
  from __future__ import annotations
2
2
 
3
- from typing import Any, List
3
+ from typing import Any
4
4
 
5
5
  from pydantic import BaseModel
6
6
 
@@ -23,7 +23,7 @@ class Value(BaseModel):
23
23
  class MarkItem(BaseModel):
24
24
  id: int
25
25
  value: str
26
- values: List[Value]
26
+ values: list[Value]
27
27
  comment: str
28
28
  weight: int
29
29
  point_date: Any
@@ -42,4 +42,4 @@ class MarkItem(BaseModel):
42
42
 
43
43
 
44
44
  class Marks(BaseModel):
45
- payload: List[MarkItem]
45
+ payload: list[MarkItem]
@@ -1,6 +1,6 @@
1
1
  from __future__ import annotations
2
2
 
3
- from typing import Any, List, Optional
3
+ from typing import Any
4
4
 
5
5
  from pydantic import BaseModel
6
6
 
@@ -44,7 +44,7 @@ class Representative(BaseModel):
44
44
  middle_name: str
45
45
  type_id: int
46
46
  type: str
47
- email: Optional[str]
47
+ email: str | None
48
48
  phone: str
49
49
  snils: str
50
50
 
@@ -74,9 +74,9 @@ class Child(BaseModel):
74
74
  class_unit_id: int
75
75
  class_uid: str
76
76
  age: int
77
- groups: List[Group]
78
- representatives: List[Representative]
79
- sections: List[Section]
77
+ groups: list[Group]
78
+ representatives: list[Representative]
79
+ sections: list[Section]
80
80
  sudir_account_exists: bool
81
81
  sudir_login: Any
82
82
  is_legal_representative: bool
@@ -90,5 +90,5 @@ class Child(BaseModel):
90
90
 
91
91
  class Profile(BaseModel):
92
92
  profile: _Profile
93
- children: List[Child]
94
- hash: str
93
+ children: list[Child]
94
+ hash: str
@@ -1,7 +1,5 @@
1
1
  from __future__ import annotations
2
2
 
3
- from typing import List
4
-
5
3
  from pydantic import BaseModel, Field
6
4
 
7
5
 
@@ -23,7 +21,7 @@ class Class(BaseModel):
23
21
  parallel: Parallel
24
22
  organization: Organization
25
23
  education_stage_id: int
26
- staff_ids: List[int]
24
+ staff_ids: list[int]
27
25
 
28
26
 
29
27
  class ServiceType(BaseModel):
@@ -34,7 +32,7 @@ class ServiceType(BaseModel):
34
32
  class EducationItem(BaseModel):
35
33
  training_begin_at: str
36
34
  training_end_at: str
37
- class_: Class = Field(..., alias='class')
35
+ class_: Class = Field(..., alias="class")
38
36
  service_type: ServiceType
39
37
 
40
38
 
@@ -48,9 +46,9 @@ class Userinfo(BaseModel):
48
46
  phone: str
49
47
  name: str
50
48
  gender: str
51
- education: List[EducationItem]
52
- children: List
53
- agents: List[str]
49
+ education: list[EducationItem]
50
+ children: list
51
+ agents: list[str]
54
52
  mesh_id: str
55
53
  given_name: str
56
54
  family_name: str
@@ -1,26 +1,28 @@
1
- from typing import Optional, Any
1
+ from typing import Any
2
2
 
3
3
 
4
4
  class APIError(Exception):
5
- def __init__(self, message: str, status_code: Optional[int] = None, response: Optional[Any] = None):
5
+ def __init__(
6
+ self,
7
+ message: str,
8
+ status_code: int | None = None,
9
+ response: Any | None = None,
10
+ ) -> None:
6
11
  super().__init__(message)
7
12
  self.status_code = status_code
8
13
  self.response = response
9
14
 
10
- def __str__(self):
11
- return f"{self.__class__.__name__}: {self.args[0]} (status={self.status_code})"
15
+ def __str__(self) -> str:
16
+ return f"{self.__class__.__name__}: {self.args[0]} ({self.status_code}) {self.response}"
12
17
 
13
18
 
14
- class AuthError(APIError):
15
- ...
19
+ class AuthError(APIError): ...
16
20
 
17
- class NotFoundError(APIError):
18
- ...
19
21
 
22
+ class NotFoundError(APIError): ...
20
23
 
21
- class ServerError(APIError):
22
- ...
23
24
 
25
+ class ServerError(APIError): ...
24
26
 
25
- class HTTPError(APIError):
26
- ...
27
+
28
+ class HTTPError(APIError): ...
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: schoolmospy
3
- Version: 0.2.1
3
+ Version: 0.2.2
4
4
  Summary: A lightweight async Python wrapper for school.mos.ru APIs
5
5
  License: GPL-3.0-only
6
6
  License-File: LICENSE
@@ -0,0 +1,18 @@
1
+ schoolmospy/__init__.py,sha256=veFE2dpRaFNhv2GhCGv9cwU341HKt2SoXIGEn3BWGZA,188
2
+ schoolmospy/__main__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
3
+ schoolmospy/core/basic_client.py,sha256=jXe94Q0ioWFHBYYeiE7T217QMYpVHzHDXW9AMpvNxsc,3103
4
+ schoolmospy/core/events_client.py,sha256=MCtXj8aR8pEPh_kYtrzVYWZcDBPoHBUyxi2qNIVwaNk,2134
5
+ schoolmospy/core/homeworks_client.py,sha256=ycXPs5Za1opuoz0Y2A63ZLgT2K8M0SeE_45Wdy3jm6U,1825
6
+ schoolmospy/core/marks_client.py,sha256=ukBB-eYs9rlZb2otxNZu7ak1u8s4M16NtSeuIgAnocA,1554
7
+ schoolmospy/core/student_client.py,sha256=MfW24G7oDzGN643GDUV-Kye_BJmHgSKLa-tRFnXix4k,1343
8
+ schoolmospy/models/events.py,sha256=NCqfqjMIMEKZJGf0gWF1tnJfCAg3ET-SJG6wRKTJG6c,867
9
+ schoolmospy/models/homeworks.py,sha256=oiHHe2jTifc_5oIWKopymcsL4MBZQgoPb3c9q3hPl7E,976
10
+ schoolmospy/models/marks.py,sha256=Vd3c-7c8SNul4oPcrbK2T-4apSE4kl97GuwaHH5gNuA,754
11
+ schoolmospy/models/profile.py,sha256=vphn7so3X0gxqkmrwDzk6i5KP1U2ejOjeqKyVPLlFJo,1630
12
+ schoolmospy/models/userinfo.py,sha256=G7uphP0CdviQxpdjGdv1xpCA84EzkID83F6TI4W57Wo,984
13
+ schoolmospy/utils/exceptions.py,sha256=XemBxgi_7NElaO7W-_6xLZHmAU9NIAeNH2yZqAzgHtQ,570
14
+ schoolmospy/utils/logging.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
15
+ schoolmospy-0.2.2.dist-info/METADATA,sha256=8D26pY9mAJij3SVnFA9YRMDeSj7aNzA_jENP3T0w_Kc,2953
16
+ schoolmospy-0.2.2.dist-info/WHEEL,sha256=zp0Cn7JsFoX2ATtOhtaFYIiE2rmFAD4OcMhtUki8W3U,88
17
+ schoolmospy-0.2.2.dist-info/licenses/LICENSE,sha256=OXLcl0T2SZ8Pmy2_dmlvKuetivmyPd5m1q-Gyd-zaYY,35149
18
+ schoolmospy-0.2.2.dist-info/RECORD,,
@@ -1,18 +0,0 @@
1
- schoolmospy/__init__.py,sha256=TC7F5zn-EtDtAv0xJpNlIuAEcqT94ih269zYKnE3dS8,111
2
- schoolmospy/__main__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
3
- schoolmospy/core/basic_client.py,sha256=_ikd_44Hlq8fm7tiYwrq917zyVl5TgrKnpwFZSZ3wbE,3010
4
- schoolmospy/core/events_client.py,sha256=NZeq43nEl_Yspa5NJ8CGTyOi10GMToS6o2M7cnlzoVI,2145
5
- schoolmospy/core/homeworks_client.py,sha256=Y_qdQBQmwkub0O6KzLeYlhuFdMEJutUx9BmrdHafpwQ,1815
6
- schoolmospy/core/marks_client.py,sha256=RxERCe-DJcMNTBogpd7NFeX8Nu2DB5p9nHDS5p6Baw0,1543
7
- schoolmospy/core/student_client.py,sha256=XxoHc2mMeg-hmdjmgdTH722m5_XUo3H1z78qO8bVX0c,1428
8
- schoolmospy/models/events.py,sha256=USmokcw5LwvXfbU28u9BJ3mzkNXkuijTSEEfw_g8nnE,921
9
- schoolmospy/models/homeworks.py,sha256=IBlNAUDmdFfbJFhEqutPVf1JHkXljTEhZ3EiaA8ddRU,1000
10
- schoolmospy/models/marks.py,sha256=ibxR8wKgfb2LQxLdH1BQJJqv-4AO0uTGH698l3dQxi8,759
11
- schoolmospy/models/profile.py,sha256=UivTgSNFFr_Eic9Dethq-ROBLLUgCFhQcrnnhKaz8tc,1648
12
- schoolmospy/models/userinfo.py,sha256=_-hY0ZOBU15w12B3FpiilTJxkD8rYNxi1UNCt5D0pY0,1009
13
- schoolmospy/utils/exceptions.py,sha256=AvfHEB2gYbJCbg4w_WTPx_2yhf8sRbyXYy1jMe_XM1U,538
14
- schoolmospy/utils/logging.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
15
- schoolmospy-0.2.1.dist-info/METADATA,sha256=PURB334-0yDJY4JJ7727Lx9nztKjsq6zv7txS2xygU0,2953
16
- schoolmospy-0.2.1.dist-info/WHEEL,sha256=zp0Cn7JsFoX2ATtOhtaFYIiE2rmFAD4OcMhtUki8W3U,88
17
- schoolmospy-0.2.1.dist-info/licenses/LICENSE,sha256=OXLcl0T2SZ8Pmy2_dmlvKuetivmyPd5m1q-Gyd-zaYY,35149
18
- schoolmospy-0.2.1.dist-info/RECORD,,