1080 lines
37 KiB
Python
1080 lines
37 KiB
Python
from datetime import datetime, timedelta
|
|
|
|
from librus_tricks.exceptions import SessionRequired, APIPathIsEmpty
|
|
|
|
|
|
class _RemoteObjectsUIDManager:
|
|
"""
|
|
Menadżer obiektów, które dopiero zostaną utworzone.
|
|
"""
|
|
|
|
def __init__(self, session, parent):
|
|
"""
|
|
|
|
:param librus_tricks.core.SynergiaClient session: Obiekt sesji
|
|
"""
|
|
self.__storage = dict()
|
|
self._session = session
|
|
self.__parent = parent
|
|
|
|
def set_object(self, attr, uid, cls):
|
|
"""
|
|
Zapisuje dane przyszłego obiektu.
|
|
|
|
:param str attr: Nazwa przyszłego property
|
|
:param int uid: Id obiektu
|
|
:param cls: Klasa obiektu
|
|
"""
|
|
self.__storage[attr] = uid, cls
|
|
# self.__parent.__setattr__(attr, cls.create(uid=uid, session=self.__session))
|
|
return self
|
|
|
|
def set_value(self, attr, val):
|
|
"""
|
|
Ustawia obiekt.
|
|
|
|
:param str attr: Nazwa obiektu
|
|
:param val: Obiekt
|
|
"""
|
|
self.__storage[attr] = val
|
|
return self
|
|
|
|
def assembly(self, attr):
|
|
"""
|
|
Pobiera wcześniej zapisany obiekt.
|
|
|
|
:param str attr: Nazwa property
|
|
:return: Żądany obiekt
|
|
"""
|
|
uid, cls = self.__storage[attr]
|
|
return cls.create(uid=uid, session=self._session)
|
|
|
|
def return_id(self, attr):
|
|
"""
|
|
Zwraca id obiektu.
|
|
|
|
:param str attr: Nazwa property
|
|
:rtype: int
|
|
:return: Id obiektu
|
|
"""
|
|
return self.__storage[attr][0]
|
|
|
|
|
|
class SynergiaGenericClass:
|
|
"""
|
|
Klasa macierzysta dla obiektów dziennika Synergia.
|
|
"""
|
|
|
|
def __init__(self, uid, resource, session):
|
|
"""
|
|
|
|
:param str uid: Id żądanego obiektu
|
|
:param librus_tricks.core.SynergiaClient session: Obiekt sesji
|
|
:param resource: ścieżka do źródła danych
|
|
:type resource: iterable of str
|
|
:param str extraction_key: str zawierający klucz do wyjęcia danych
|
|
:param dict resource: dict zawierający gotowe dane (np. załadowane z cache)
|
|
"""
|
|
|
|
self._session = session
|
|
self.uid = uid
|
|
self.objects = _RemoteObjectsUIDManager(self._session, self)
|
|
self._json_resource = resource
|
|
|
|
# Of course i can comment it out, but for code completion props will be better
|
|
# def __getattr__(self, name):
|
|
# return self.objects_ids.assembly(name)
|
|
|
|
@classmethod
|
|
def assembly(cls, resource, session):
|
|
"""
|
|
Umożliwia stworzenie obiektu posiadając dict i obiekt sesji.
|
|
|
|
:param dict resource: Gotowe dane do stworzenia obiektu
|
|
:param librus_tricks.core.SynergiaClient session: Obiekt sesji
|
|
:return: Nowy obiekt
|
|
"""
|
|
self = cls(resource['Id'], resource, session)
|
|
return self
|
|
|
|
@classmethod
|
|
def create(cls, uid=None, path=('',), session=None, extraction_key=None, expire=timedelta(seconds=1)):
|
|
"""
|
|
Pobiera i składa nowy obiekt.
|
|
|
|
:param int uid: Id obiektu
|
|
:param tuple of str path: Niezłożona ścieżka API
|
|
:param librus_tricks.core.SynergiaClient session: Obiekt sesji
|
|
:param str extraction_key: Klucz do wyciągnięcia danych
|
|
:return: Pobrany obiekt
|
|
"""
|
|
import logging
|
|
|
|
if uid is None or session is None:
|
|
raise SessionRequired()
|
|
|
|
maybe_response = session.cache.get_object(uid, cls)
|
|
if not maybe_response is None:
|
|
logging.debug('Returning %s %s from object cache', maybe_response, uid)
|
|
return maybe_response
|
|
|
|
if path == ('',):
|
|
raise APIPathIsEmpty(f'Path for {cls.__name__} class is empty!')
|
|
|
|
response = session.get_cached_response(*path, uid, max_lifetime=expire)
|
|
logging.debug('Returning %s %s object from response cache', cls.__name__, uid)
|
|
|
|
if extraction_key is None:
|
|
extraction_key = SynergiaGenericClass.auto_extract(response)
|
|
|
|
resource = response[extraction_key]
|
|
self = cls(resource['Id'], resource, session)
|
|
return self
|
|
|
|
@staticmethod
|
|
def auto_extract(payload):
|
|
"""
|
|
Próbuje automatycznie wydobyć klucz.
|
|
|
|
:param dict payload:
|
|
:return: Wydobyty klucz
|
|
:rtype: str
|
|
"""
|
|
for key in payload.keys():
|
|
if key not in ('Resources', 'Url'):
|
|
return key
|
|
return
|
|
|
|
def export_resource(self):
|
|
return self._json_resource.copy()
|
|
|
|
def __repr__(self):
|
|
return f'<{self.__class__.__name__} {self.uid} at {hex(id(self))}>'
|
|
|
|
def __hash__(self):
|
|
return hash(self.uid)
|
|
|
|
def __eq__(self, other):
|
|
if isinstance(other, self.__class__):
|
|
return self.uid == other.uid
|
|
raise TypeError(f'Object is not instance of {self.__class__.__name__}')
|
|
|
|
def __ne__(self, other):
|
|
return not self.__eq__(other)
|
|
|
|
def _is_compatible(self, other):
|
|
if not isinstance(other, self.__class__):
|
|
raise TypeError()
|
|
return True
|
|
|
|
|
|
class SynergiaTeacher(SynergiaGenericClass):
|
|
def __init__(self, uid, resource, session):
|
|
super().__init__(uid, resource, session)
|
|
self.name = self._json_resource['FirstName']
|
|
self.last_name = self._json_resource['LastName']
|
|
|
|
@classmethod
|
|
def create(cls, uid=None, path=('Users',), session=None, extraction_key='User', expire=timedelta(days=31)):
|
|
return super().create(uid, path, session, extraction_key, expire)
|
|
|
|
def __repr__(self):
|
|
return f'<{self.__class__.__name__} {self.name} {self.last_name}>'
|
|
|
|
def __str__(self):
|
|
return f'{self.name} {self.last_name}'
|
|
|
|
|
|
class SynergiaStudent(SynergiaTeacher):
|
|
pass
|
|
|
|
|
|
class SynergiaGlobalClass(SynergiaGenericClass):
|
|
"""Klasa reprezentująca klasę (np. 1C)"""
|
|
|
|
def __init__(self, uid, resource, session):
|
|
"""
|
|
Tworzy obiekt reprezentujący klasę (jako zbiór uczniów)
|
|
|
|
:param str uid: id klasy
|
|
:param librus_tricks.core.SynergiaClient session: obiekt sesji z API Synergii
|
|
:param dict resource: dane z json'a
|
|
"""
|
|
super().__init__(uid, resource, session)
|
|
|
|
self.alias = f'{self._json_resource["Number"]}{self._json_resource["Symbol"]}'
|
|
self.begin_date = datetime.strptime(self._json_resource['BeginSchoolYear'], '%Y-%m-%d').date()
|
|
self.end_date = datetime.strptime(self._json_resource['EndSchoolYear'], '%Y-%m-%d').date()
|
|
self.objects.set_object(
|
|
'tutor', self._json_resource['ClassTutor']['Id'], SynergiaTeacher
|
|
)
|
|
|
|
@property
|
|
def tutor(self) -> SynergiaTeacher:
|
|
return self.objects.assembly('tutor')
|
|
|
|
def __repr__(self):
|
|
return f'<{self.__class__.__name__} {self.alias}>'
|
|
|
|
|
|
class SynergiaVirtualClass(SynergiaGenericClass):
|
|
def __init__(self, uid, resource, session):
|
|
"""
|
|
Tworzy obiekt reprezentujący grupę uczniów
|
|
|
|
:param str uid: id klasy
|
|
:param librus_tricks.core.SynergiaClient session: obiekt sesji z API Synergii
|
|
:param dict resource: dane z json'a
|
|
"""
|
|
super().__init__(uid, resource, session)
|
|
|
|
self.name = self._json_resource['Name']
|
|
self.number = self._json_resource['Number']
|
|
self.symbol = self._json_resource['Symbol']
|
|
self.objects.set_object(
|
|
'teacher', self._json_resource['Teacher']['Id'], SynergiaTeacher
|
|
).set_object(
|
|
'subject', self._json_resource['Subject']['Id'], SynergiaSubject
|
|
)
|
|
|
|
def __repr__(self):
|
|
return f'<{self.__class__.__name__} {self.name}>'
|
|
|
|
@property
|
|
def teacher(self) -> SynergiaTeacher:
|
|
return self.objects.assembly('teacher')
|
|
|
|
@property
|
|
def subject(self):
|
|
return self.objects.assembly('subject')
|
|
|
|
|
|
class SynergiaSubject(SynergiaGenericClass):
|
|
def __init__(self, uid, resource, session):
|
|
super().__init__(uid, resource, session)
|
|
self.name = self._json_resource['Name']
|
|
self.short_name = self._json_resource['Short']
|
|
|
|
@classmethod
|
|
def create(cls, uid=None, path=('Subjects',), session=None, extraction_key='Subject', expire=timedelta(days=31)):
|
|
return super().create(uid, path, session, extraction_key, expire)
|
|
|
|
def __repr__(self):
|
|
return f'<{self.__class__.__name__} {self.name}>'
|
|
|
|
def __str__(self):
|
|
return self.name
|
|
|
|
|
|
class SynergiaLesson(SynergiaGenericClass):
|
|
def __init__(self, uid, resource, session):
|
|
"""
|
|
Klasa reprezentująca jednostkową lekcję
|
|
|
|
:type session: librus_tricks.core.SynergiaClient
|
|
"""
|
|
super().__init__(uid, resource, session)
|
|
|
|
self.objects.set_object(
|
|
'teacher', self._json_resource['Teacher']['Id'], SynergiaTeacher
|
|
).set_object(
|
|
'subject', self._json_resource['Subject']['Id'], SynergiaSubject
|
|
)
|
|
|
|
@classmethod
|
|
def create(cls, uid=None, path=('Lessons',), session=None, extraction_key='Lesson', expire=timedelta(minutes=5)):
|
|
return super().create(uid, path, session, extraction_key, expire)
|
|
|
|
@property
|
|
def teacher(self) -> SynergiaTeacher:
|
|
return self.objects.assembly('teacher')
|
|
|
|
@property
|
|
def subject(self) -> SynergiaSubject:
|
|
return self.objects.assembly('subject')
|
|
|
|
|
|
class SynergiaGradeCategory(SynergiaGenericClass):
|
|
def __init__(self, uid, resource, session):
|
|
super().__init__(uid, resource, session)
|
|
|
|
def __try_to_extract(payload, extraction_key, false_return=None):
|
|
if extraction_key in payload.keys():
|
|
return payload[extraction_key]
|
|
return false_return
|
|
|
|
self.count_to_the_average = self._json_resource['CountToTheAverage']
|
|
self.name = self._json_resource['Name']
|
|
self.obligation_to_perform = self._json_resource['ObligationToPerform']
|
|
self.standard = self._json_resource['Standard']
|
|
self.weight = __try_to_extract(self._json_resource, 'Weight', false_return=0)
|
|
|
|
if 'Teacher' in self._json_resource.keys():
|
|
self.objects.set_object(
|
|
'teacher', self._json_resource['Id'], SynergiaTeacher
|
|
)
|
|
|
|
@classmethod
|
|
def create(cls, uid=None, path=('Grades', 'Categories'), session=None, extraction_key='Category',
|
|
expire=timedelta(days=31)):
|
|
return super().create(uid, path, session, extraction_key, expire)
|
|
|
|
@property
|
|
def teacher(self):
|
|
try:
|
|
return self.objects.assembly('teacher')
|
|
except KeyError:
|
|
return
|
|
|
|
def __repr__(self):
|
|
return f'<{self.__class__.__name__} {self.name}>'
|
|
|
|
|
|
class SynergiaGradeComment(SynergiaGenericClass):
|
|
def __init__(self, uid, resource, session):
|
|
super().__init__(uid, resource, session)
|
|
|
|
self.text = self._json_resource['Text']
|
|
self.objects.set_object(
|
|
'teacher', self._json_resource['AddedBy']['Id'], SynergiaTeacher
|
|
).set_object(
|
|
'bind', self._json_resource['Grade']['Id'], SynergiaGrade
|
|
)
|
|
|
|
def __str__(self):
|
|
return self.text
|
|
|
|
@classmethod
|
|
def create(cls, uid=None, path=('Grades', 'Comments'), session=None, extraction_key='Comment',
|
|
expire=timedelta(days=31)):
|
|
return super().create(uid, path, session, extraction_key, expire)
|
|
|
|
@property
|
|
def teacher(self) -> SynergiaTeacher:
|
|
return self.objects.assembly('teacher')
|
|
|
|
@property
|
|
def grade_bind(self):
|
|
return self.objects.assembly('bind')
|
|
|
|
def __repr__(self):
|
|
return f'<{self.__class__.__name__} {self.text}>'
|
|
|
|
|
|
class SynergiaBaseTextGrade(SynergiaGenericClass):
|
|
def __init__(self, uid, resource, session):
|
|
super().__init__(uid, resource, session)
|
|
|
|
self.add_date = datetime.strptime(self._json_resource['AddDate'], '%Y-%m-%d %H:%M:%S')
|
|
self.date = datetime.strptime(self._json_resource['Date'], '%Y-%m-%d').date()
|
|
self.grade = self._json_resource['Grade']
|
|
self.semester = self._json_resource['Semester']
|
|
self.visible = self._json_resource['ShowInGradesView']
|
|
self.objects.set_object(
|
|
'teacher', self._json_resource['AddedBy']['Id'], SynergiaTeacher
|
|
).set_object(
|
|
'subject', self._json_resource['Subject']['Id'], SynergiaSubject
|
|
).set_object(
|
|
'student', self._json_resource['Student']['Id'], SynergiaStudent
|
|
)
|
|
|
|
@classmethod
|
|
def create(cls, uid=None, path=('BaseTextGrades',), session=None, extraction_key='BaseTextGrades',
|
|
expire=timedelta(minutes=5)):
|
|
return super().create(uid, path, session, extraction_key, expire)
|
|
|
|
@property
|
|
def teacher(self) -> SynergiaTeacher:
|
|
return self.objects.assembly('teacher')
|
|
|
|
@property
|
|
def subject(self) -> SynergiaSubject:
|
|
return self.objects.assembly('subject')
|
|
|
|
@property
|
|
def student(self):
|
|
return self.objects.assembly('student')
|
|
|
|
|
|
class SynergiaGrade(SynergiaGenericClass):
|
|
def __init__(self, uid, resource, session):
|
|
super().__init__(uid, resource, session)
|
|
|
|
class GradeMetadata:
|
|
def __init__(self, is_c, is_s, is_sp, is_f, is_fp):
|
|
self.is_constituent = is_c
|
|
self.is_semester_grade = is_s
|
|
self.is_semester_grade_proposition = is_sp
|
|
self.is_final_grade = is_f
|
|
self.is_final_grade_proposition = is_fp
|
|
|
|
self.add_date = datetime.strptime(self._json_resource['AddDate'], '%Y-%m-%d %H:%M:%S')
|
|
self.date = datetime.strptime(self._json_resource['Date'], '%Y-%m-%d').date()
|
|
self.grade = self._json_resource['Grade']
|
|
self.is_constituent = self._json_resource['IsConstituent']
|
|
self.semester = self._json_resource['Semester']
|
|
self.metadata = GradeMetadata(
|
|
self._json_resource['IsConstituent'],
|
|
self._json_resource['IsSemester'],
|
|
self._json_resource['IsSemesterProposition'],
|
|
self._json_resource['IsFinal'],
|
|
self._json_resource['IsFinalProposition']
|
|
)
|
|
|
|
self.objects.set_object(
|
|
'teacher', self._json_resource['AddedBy']['Id'], SynergiaTeacher
|
|
).set_object(
|
|
'subject', self._json_resource['Subject']['Id'], SynergiaSubject
|
|
).set_object(
|
|
'category', self._json_resource['Category']['Id'], SynergiaGradeCategory
|
|
)
|
|
|
|
@property
|
|
def is_special(self):
|
|
m = self.metadata
|
|
if m.is_final_grade or m.is_final_grade_proposition or m.is_semester_grade or m.is_semester_grade_proposition:
|
|
return True
|
|
return False
|
|
|
|
def __repr__(self):
|
|
return f'<{self.__class__.__name__} {self.grade} from SynergiaSubject with id {self.objects.return_id("subject")} ' \
|
|
f'added {self.add_date.strftime("%Y-%m-%d %H:%M:%S")}>'
|
|
|
|
def __str__(self):
|
|
return self.grade
|
|
|
|
@property
|
|
def teacher(self) -> SynergiaTeacher:
|
|
return self.objects.assembly('teacher')
|
|
|
|
@property
|
|
def subject(self) -> SynergiaSubject:
|
|
return self.objects.assembly('subject')
|
|
|
|
@property
|
|
def category(self) -> SynergiaGradeCategory:
|
|
return self.objects.assembly('category')
|
|
|
|
@property
|
|
def comments(self):
|
|
"""
|
|
|
|
:rtype: list of SynergiaGradeComment
|
|
"""
|
|
if self._json_resource.get('Comments') is not None:
|
|
return [
|
|
SynergiaGradeComment.create(
|
|
uid=com.get('Id'), session=self._session
|
|
) for com in self._json_resource.get('Comments')
|
|
]
|
|
return tuple()
|
|
|
|
@property
|
|
def real_value(self):
|
|
return {
|
|
'1': 1,
|
|
'1+': 1.5,
|
|
'2-': 1.75,
|
|
'2': 2,
|
|
'2+': 2.5,
|
|
'3-': 2.75,
|
|
'3': 3,
|
|
'3+': 3.5,
|
|
'4-': 3.75,
|
|
'4': 4,
|
|
'4+': 4.5,
|
|
'5-': 4.75,
|
|
'5': 5,
|
|
'5+': 5.5,
|
|
'6-': 5.75,
|
|
'6': 6
|
|
}.get(self.grade)
|
|
|
|
@classmethod
|
|
def create(cls, uid=None, path=('Grades',), session=None, extraction_key='Grade', expire=timedelta(minutes=45)):
|
|
return super().create(uid, path, session, extraction_key, expire)
|
|
|
|
def __eq__(self, other):
|
|
self._is_compatible(other)
|
|
return self.real_value == other.real_value and self.category.weight
|
|
|
|
def __gt__(self, other):
|
|
self._is_compatible(other)
|
|
return self.real_value > other.real_value and self.category.weight >= other.category.weight
|
|
|
|
def __ge__(self, other):
|
|
self._is_compatible(other)
|
|
return self.real_value >= other.real_value and self.category.weight >= other.category.weight
|
|
|
|
def __lt__(self, other):
|
|
self._is_compatible(other)
|
|
return self.real_value < other.real_value and self.category.weight <= other.category.weight
|
|
|
|
def __le__(self, other):
|
|
self._is_compatible(other)
|
|
return self.real_value <= other.real_value and self.category.weight <= other.category.weight
|
|
|
|
|
|
class SynergiaAttendanceType(SynergiaGenericClass):
|
|
def __init__(self, uid, resource, session):
|
|
super().__init__(uid, resource, session)
|
|
self.color = self._json_resource['ColorRGB']
|
|
self.is_presence_kind = self._json_resource['IsPresenceKind']
|
|
self.name = self._json_resource['Name']
|
|
self.short_name = self._json_resource['Short']
|
|
|
|
@classmethod
|
|
def create(cls, uid=None, path=('Attendances', 'Types'), session=None, extraction_key='Type',
|
|
expire=timedelta(days=31)):
|
|
return super().create(uid, path, session, extraction_key, expire)
|
|
|
|
def __repr__(self):
|
|
return f'<{self.__class__.__name__} {self.short_name}>'
|
|
|
|
def __str__(self):
|
|
return self.name
|
|
|
|
|
|
class SynergiaAttendance(SynergiaGenericClass):
|
|
def __init__(self, uid, resource, session):
|
|
super().__init__(uid, resource, session)
|
|
self.add_date = datetime.strptime(self._json_resource['AddDate'], '%Y-%m-%d %H:%M:%S')
|
|
self.date = datetime.strptime(self._json_resource['Date'], '%Y-%m-%d').date()
|
|
self.lesson_no = int(self._json_resource['LessonNo'])
|
|
self.objects.set_object(
|
|
'teacher', self._json_resource['AddedBy']['Id'], SynergiaTeacher
|
|
).set_object(
|
|
'student', self._json_resource['Student']['Id'], SynergiaStudent
|
|
).set_object(
|
|
'type', self._json_resource['Type']['Id'], SynergiaAttendanceType
|
|
).set_object(
|
|
'lesson', resource['Lesson']['Id'], SynergiaLesson
|
|
)
|
|
|
|
@classmethod
|
|
def create(cls, uid=None, path=('Attendances',), session=None, extraction_key='Attendance',
|
|
expire=timedelta(minutes=10)):
|
|
return super().create(uid, path, session, extraction_key, expire)
|
|
|
|
@property
|
|
def teacher(self):
|
|
"""
|
|
:rtype: SynergiaTeacher
|
|
"""
|
|
return self.objects.assembly('teacher')
|
|
|
|
@property
|
|
def student(self):
|
|
"""
|
|
:rtype: SynergiaStudent
|
|
"""
|
|
return self.objects.assembly('student')
|
|
|
|
@property
|
|
def type(self):
|
|
"""
|
|
:rtype: SynergiaAttendanceType
|
|
"""
|
|
return self.objects.assembly('type')
|
|
|
|
@property
|
|
def lesson(self):
|
|
"""
|
|
:rtype: librus_tricks.classes.SynergiaLesson
|
|
"""
|
|
return self.objects.assembly('lesson')
|
|
|
|
def __repr__(self):
|
|
return f'<SynergiaAttendance at {self.date.isoformat()} lesson {self.lesson_no}>'
|
|
|
|
def __str__(self):
|
|
return self.type.__str__()
|
|
|
|
|
|
class SynergiaExamCategory(SynergiaGenericClass):
|
|
def __init__(self, uid, resource, session):
|
|
super().__init__(uid, resource, session)
|
|
|
|
self.name = self._json_resource['Name']
|
|
self.objects.set_object('color', self._json_resource['Color']['Id'], SynergiaColor)
|
|
|
|
@classmethod
|
|
def create(cls, uid=None, path=('HomeWorks', 'Categories'), session=None, extraction_key='Category',
|
|
expire=timedelta(days=31)):
|
|
return super().create(uid, path, session, extraction_key, expire)
|
|
|
|
@property
|
|
def color(self):
|
|
"""
|
|
|
|
:rtype: SynergiaColor
|
|
"""
|
|
return self.objects.assembly('color')
|
|
|
|
def __str__(self):
|
|
return self.name
|
|
|
|
|
|
class SynergiaExam(SynergiaGenericClass):
|
|
def __init__(self, uid, resource, session):
|
|
|
|
super().__init__(uid, resource, session)
|
|
|
|
self.add_date = datetime.strptime(self._json_resource['AddDate'], '%Y-%m-%d %H:%M:%S')
|
|
self.content = self._json_resource['Content']
|
|
self.date = datetime.strptime(self._json_resource['Date'], '%Y-%m-%d').date()
|
|
self.lesson = self._json_resource['LessonNo']
|
|
if self._json_resource['TimeFrom'] is None:
|
|
self.time_start = None
|
|
else:
|
|
self.time_start = datetime.strptime(self._json_resource['TimeFrom'], '%H:%M:%S').time()
|
|
if self._json_resource['TimeTo'] is None:
|
|
self.time_end = None
|
|
else:
|
|
self.time_end = datetime.strptime(self._json_resource['TimeTo'], '%H:%M:%S').time()
|
|
|
|
self.objects.set_object(
|
|
'teacher', self._json_resource['CreatedBy']['Id'], SynergiaTeacher
|
|
).set_object(
|
|
'category', self._json_resource['Category']['Id'], SynergiaExamCategory
|
|
)
|
|
if 'Subject' in self._json_resource:
|
|
self.objects.set_object('subject', self._json_resource['Subject']['Id'], SynergiaSubject)
|
|
self.__subject_present = True
|
|
else:
|
|
self.__subject_present = False
|
|
|
|
@classmethod
|
|
def create(cls, uid=None, path=('HomeWorks',), session=None, extraction_key='HomeWork', expire=timedelta(days=3)):
|
|
return super().create(uid, path, session, extraction_key, expire)
|
|
|
|
def __repr__(self):
|
|
return f'<{self.__class__.__name__} ' \
|
|
f'{self.date.strftime("%Y-%m-%d")} for subject {self.subject}>'
|
|
|
|
@property
|
|
def teacher(self) -> SynergiaTeacher:
|
|
return self.objects.assembly('teacher')
|
|
|
|
# @property
|
|
# def group(self):
|
|
# """
|
|
#
|
|
# :rtype: SynergiaGlobalClass
|
|
# :rtype: SynergiaVirtualClass
|
|
# """
|
|
# if self.objects_ids.group_type is SynergiaGlobalClass:
|
|
# return SynergiaGlobalClass(self.objects_ids.group, self._session)
|
|
# else:
|
|
# return SynergiaVirtualClass(self.objects_ids.group, self._session)
|
|
|
|
@property
|
|
def subject(self):
|
|
if self.__subject_present:
|
|
return self.objects.assembly('subject')
|
|
return None
|
|
|
|
@property
|
|
def category(self):
|
|
return self.objects.assembly('category')
|
|
|
|
|
|
class SynergiaColor(SynergiaGenericClass):
|
|
def __init__(self, uid, resource, session):
|
|
super().__init__(uid, resource, session)
|
|
self.name = self._json_resource['Name']
|
|
self.hex_rgb = self._json_resource['RGB']
|
|
|
|
@classmethod
|
|
def create(cls, uid=None, path=('Colors',), session=None, extraction_key='Color', expire=timedelta(days=31)):
|
|
return super().create(uid, path, session, extraction_key, expire)
|
|
|
|
def __repr__(self):
|
|
return f'<{self.__class__.__name__} {self.hex_rgb}>'
|
|
|
|
def __str__(self):
|
|
return self.hex_rgb
|
|
|
|
|
|
class SynergiaClassroom(SynergiaGenericClass):
|
|
def __init__(self, uid, resource, session):
|
|
super().__init__(uid, resource, session)
|
|
self.name = self._json_resource['Name']
|
|
self.symbol = self._json_resource['Symbol']
|
|
|
|
@classmethod
|
|
def create(cls, uid=None, path=('Classrooms',), session=None, extraction_key=None, expire=timedelta(days=31)):
|
|
return super().create(uid, path, session, extraction_key, expire)
|
|
|
|
def __repr__(self):
|
|
return f'<SynergiaClassroom {self.symbol}>'
|
|
|
|
def __str__(self):
|
|
return self.name
|
|
|
|
|
|
class SynergiaTeacherFreeDaysTypes(SynergiaGenericClass):
|
|
def __init__(self, uid, resource, session):
|
|
super().__init__(uid, resource, session)
|
|
self.name = self._json_resource[0]['Name']
|
|
|
|
|
|
class SynergiaTeacherFreeDays(SynergiaGenericClass):
|
|
def __init__(self, uid, resource, session):
|
|
super().__init__(uid, resource, session)
|
|
|
|
self.starts = datetime.strptime(self._json_resource['DateFrom'], '%Y-%m-%d').date()
|
|
self.ends = datetime.strptime(self._json_resource['DateTo'], '%Y-%m-%d').date()
|
|
self.objects.set_object(
|
|
'teacher', self._json_resource['Teacher']['Id'], SynergiaTeacher
|
|
)
|
|
|
|
if self._json_resource.get('TimeTo') is not None:
|
|
self.time_begin = datetime.strptime(self._json_resource['TimeFrom'], '%H:%M:%S').time()
|
|
self.time_ends = datetime.strptime(self._json_resource['TimeTo'], '%H:%M:%S').time()
|
|
else:
|
|
self.time_begin = None
|
|
self.time_ends = None
|
|
|
|
@property
|
|
def period_length(self):
|
|
return self.ends - self.starts
|
|
|
|
@property
|
|
def teacher(self) -> SynergiaTeacher:
|
|
"""
|
|
|
|
:rtype: SynergiaTeacher
|
|
"""
|
|
return self.objects.assembly('teacher')
|
|
|
|
def __repr__(self):
|
|
return f'<SynergiaTeacherFreeDays {self.starts.isoformat()} - {self.ends.isoformat()} ({(self.ends - self.starts).days} days) for {self.objects.return_id("teacher")}>'
|
|
|
|
|
|
class SynergiaSchoolFreeDays(SynergiaGenericClass):
|
|
def __init__(self, uid, resource, session):
|
|
super().__init__(uid, resource, session)
|
|
self.starts = datetime.strptime(self._json_resource['DateFrom'], '%Y-%m-%d').date()
|
|
self.ends = datetime.strptime(self._json_resource['DateTo'], '%Y-%m-%d').date()
|
|
self.name = self._json_resource['Name']
|
|
|
|
@classmethod
|
|
def create(cls, uid=None, path=('Calendars', 'SchoolFreeDays'), session=None, extraction_key='SchoolFreeDays',
|
|
expire=timedelta(minutes=5)):
|
|
return super().create(uid, path, session, extraction_key, expire)
|
|
|
|
def __repr__(self):
|
|
return f'<{self.__class__.__name__} {self.starts.isoformat()} - {self.ends.isoformat()}>'
|
|
|
|
|
|
class SynergiaTimetableEntry(SynergiaGenericClass):
|
|
def __init__(self, uid, resource, session):
|
|
super().__init__(uid, resource, session)
|
|
self.available = datetime.strptime(resource['DateFrom'], '%Y-%m-%d').date(), \
|
|
datetime.strptime(resource['DateTo'], '%Y-%m-%d').date()
|
|
|
|
@classmethod
|
|
def create(cls, uid=None, path=('TimetableEntries',), session=None, extraction_key='TimetableEntry',
|
|
expire=timedelta(seconds=15)):
|
|
return super().create(uid, path, session, extraction_key, expire)
|
|
|
|
|
|
class SynergiaTimetableEvent:
|
|
def __init__(self, resource, session):
|
|
self.lesson_no = int(resource['LessonNo']) #: int: numer lekcji
|
|
self.start = datetime.strptime(resource['HourFrom'], '%H:%M').time() #: time: początek lekcji
|
|
self.end = datetime.strptime(resource['HourTo'], '%H:%M').time() #: time: koniec lekcji
|
|
self.is_cancelled = resource['IsCanceled'] #: bool: czy lekcja jest odwołana
|
|
self.is_sub = resource['IsSubstitutionClass'] #: bool: czy lekcja jest zastępstwem
|
|
self.preloaded = {
|
|
'subject_title': resource['Subject']['Name'],
|
|
'teacher': f'{resource["Teacher"]["FirstName"]} {resource["Teacher"]["LastName"]}'
|
|
}
|
|
self.objects = _RemoteObjectsUIDManager(session, self)
|
|
self.objects.set_object(
|
|
'subject', resource['Subject']['Id'], SynergiaSubject
|
|
).set_object(
|
|
'teacher', resource['Teacher']['Id'], SynergiaTeacher
|
|
)
|
|
|
|
self.__set_classroom(resource)
|
|
|
|
def __set_classroom(self, resource):
|
|
"""
|
|
|
|
:param dict resource:
|
|
:return:
|
|
"""
|
|
if 'Classroom' in resource.keys():
|
|
self.objects.set_object(
|
|
'classroom', resource['Classroom']['Id'], SynergiaClassroom
|
|
)
|
|
elif 'OrgClassroom' in resource.keys():
|
|
self.objects.set_object(
|
|
'classroom', resource['OrgClassroom']['Id'], SynergiaClassroom
|
|
)
|
|
else:
|
|
self.objects.set_value('classroom', None)
|
|
|
|
@property
|
|
def lesson_status(self):
|
|
if self.is_cancelled:
|
|
return 'Cancelled'
|
|
elif self.is_sub:
|
|
return 'Changed'
|
|
return 'Planned'
|
|
|
|
@property
|
|
def subject(self):
|
|
"""
|
|
:rtype: librus_tricks.classes.SynergiaSubject
|
|
"""
|
|
return self.objects.assembly('subject')
|
|
|
|
@property
|
|
def teacher(self):
|
|
"""
|
|
:rtype: librus_tricks.classes.SynergiaTeacher
|
|
"""
|
|
return self.objects.assembly('teacher')
|
|
|
|
@property
|
|
def classroom(self):
|
|
"""
|
|
:rtype: librus_tricks.classes.SynergiaClassroom
|
|
"""
|
|
return self.objects.assembly('classroom')
|
|
|
|
@property
|
|
def human_readable_time_range(self):
|
|
return f'{self.start.strftime("%H:%M")} - {self.end.strftime("%H:%M")}'
|
|
|
|
def __repr__(self):
|
|
return f'<SynergiaTimetableEvent {self.preloaded["subject_title"]} {self.start} {self.end} with {self.preloaded["teacher"]}>'
|
|
|
|
def __str__(self):
|
|
return self.preloaded["subject_title"]
|
|
|
|
|
|
class SynergiaTimetableDay:
|
|
def __init__(self, lessons):
|
|
self.lessons = tuple(lessons) #: tuple[SynergiaTimetableEvent]: krotka z lekcjami
|
|
if self.lessons.__len__() != 0:
|
|
self.day_start = self.lessons[0].start
|
|
self.day_end = self.lessons[-1].end
|
|
else:
|
|
self.day_start = None
|
|
self.day_end = None
|
|
|
|
def __repr__(self):
|
|
return f'<{self.__class__.__name__} with {self.lessons.__len__()} lessons between {self.day_start} and {self.day_end}>'
|
|
|
|
|
|
class SynergiaTimetable(SynergiaGenericClass):
|
|
"""
|
|
Obiekt zawierający cały tydzień w planie lekcji
|
|
"""
|
|
|
|
def __init__(self, uid, resource, session):
|
|
super().__init__(uid, resource, session)
|
|
self.days = self.convert_parsed_timetable(
|
|
self.parse_timetable(resource)
|
|
) #: list[SynergiaTimetableDay]: lista z dniami tygodnia
|
|
|
|
@property
|
|
def today_timetable(self):
|
|
"""
|
|
|
|
:rtype: list of SynergiaTimetableEvent
|
|
"""
|
|
return self.days[datetime.now().date()]
|
|
|
|
@classmethod
|
|
def assembly(cls, resource, session):
|
|
pseudo_id = int(datetime.now().timestamp()).__str__()
|
|
self = cls(pseudo_id, resource, session)
|
|
return self
|
|
|
|
@classmethod
|
|
def create(cls, uid=None, path=('Timetables',), session=None, extraction_key='Timetable',
|
|
expire=timedelta(seconds=15)):
|
|
response = session.get_cached_response(*path)
|
|
|
|
if extraction_key is None:
|
|
extraction_key = SynergiaGenericClass.auto_extract(response)
|
|
|
|
resource = response[extraction_key]
|
|
self = cls.assembly(resource, session)
|
|
return self
|
|
|
|
@staticmethod
|
|
def parse_timetable(resource):
|
|
root = {}
|
|
|
|
for day in resource.keys():
|
|
day_date = datetime.strptime(day, '%Y-%m-%d').date()
|
|
root[day_date] = []
|
|
for period in resource[day]:
|
|
if period.__len__() != 0:
|
|
root[day_date].append(period[0])
|
|
return root
|
|
|
|
def convert_parsed_timetable(self, timetable):
|
|
for day in timetable:
|
|
for event_index in range(len(timetable[day])):
|
|
if timetable[day][event_index].keys().__len__() != 0:
|
|
timetable[day][event_index] = SynergiaTimetableEvent(timetable[day][event_index], self._session)
|
|
|
|
for day in timetable.keys():
|
|
timetable[day] = SynergiaTimetableDay(timetable[day])
|
|
|
|
return timetable
|
|
|
|
def __repr__(self):
|
|
return f'<{self.__class__.__name__} for {self.days.keys()}>'
|
|
|
|
def __str__(self):
|
|
o_str = ''
|
|
for day_key in self.days.keys():
|
|
o_str += f'{day_key}\n'
|
|
for event in self.days[day_key]:
|
|
if event != {}:
|
|
o_str += f' {event.__str__()}\n'
|
|
return o_str
|
|
|
|
|
|
class SynergiaNativeMessageAuthor(SynergiaGenericClass):
|
|
def __init__(self, uid, resource, session):
|
|
super().__init__(uid, resource, session)
|
|
self.name = resource.get('Name')
|
|
|
|
@classmethod
|
|
def create(cls, uid=None, path=('Messages', 'User'), session=None, extraction_key='User',
|
|
expire=timedelta(days=60)):
|
|
return super().create(uid, path, session, extraction_key, expire)
|
|
|
|
def __repr__(self):
|
|
return f'<{self.__class__.__name__} {self.name}>'
|
|
|
|
@property
|
|
def matching_indentity(self):
|
|
teachers = self._session.return_objects('Users', cls=SynergiaTeacher, extraction_key='Users')
|
|
for teacher in teachers:
|
|
if str(teacher.name) in self.name and str(teacher.last_name) in self.name:
|
|
return teacher
|
|
return
|
|
|
|
|
|
class SynergiaNativeMessage(SynergiaGenericClass):
|
|
def __init__(self, uid, resource, session):
|
|
super().__init__(uid, resource, session)
|
|
self.body = self._json_resource['Body'] #: str: wiadomość
|
|
self.topic = self._json_resource['Subject'] #: str: temat
|
|
self.send_date = datetime.fromtimestamp(self._json_resource['SendDate']) #: datetime: data wysłania
|
|
self.objects.set_object('sender', self._json_resource['Sender']['Id'], SynergiaNativeMessageAuthor)
|
|
|
|
@property
|
|
def sender(self) -> SynergiaNativeMessageAuthor:
|
|
return self.objects.assembly('sender')
|
|
|
|
@classmethod
|
|
def create(cls, uid=None, path=('Messages',), session=None, extraction_key='Message', expire=timedelta(days=31)):
|
|
return super().create(uid, path, session, extraction_key, expire)
|
|
|
|
|
|
class SynergiaNews(SynergiaGenericClass):
|
|
"""
|
|
Obiekt reprezentujący ogłoszenie szkolne
|
|
"""
|
|
|
|
def __init__(self, uid, resource, session):
|
|
super().__init__(uid, resource, session)
|
|
self.content = self._json_resource['Content'] #: str: wiadomość ogłoszenia
|
|
self.created = datetime.strptime(self._json_resource['CreationDate'],
|
|
'%Y-%m-%d %H:%M:%S') #: datetime: data utworzenia
|
|
self.unique_id = self._json_resource['Id'] #: int: id ogłoszenia
|
|
self.topic = self._json_resource['Subject'] #: str: temat
|
|
self.was_read = self._json_resource['WasRead'] #: bool: status odczytania?
|
|
self.starts = datetime.strptime(self._json_resource['StartDate'], '%Y-%m-%d') #: date: ??
|
|
self.ends = datetime.strptime(self._json_resource['EndDate'], '%Y-%m-%d') #: date: ??
|
|
self.objects.set_object(
|
|
'teacher', self._json_resource['AddedBy']['Id'], SynergiaTeacher
|
|
)
|
|
|
|
@property
|
|
def teacher(self) -> SynergiaTeacher:
|
|
return self.objects.assembly('teacher')
|
|
|
|
@classmethod
|
|
def create(cls, uid=None, path=('SchoolNotices',), session=None, extraction_key='SchoolNotices',
|
|
expire=timedelta(days=31)):
|
|
return super().create(uid, path, session, extraction_key, expire)
|
|
|
|
def __repr__(self):
|
|
return f'<SynergiaNews {self.topic} posted {self.created}>'
|
|
|
|
|
|
class SynergiaSchool(SynergiaGenericClass):
|
|
"""
|
|
Obiekt zawierający informacje o szkole
|
|
"""
|
|
|
|
def __init__(self, uid, resource, session):
|
|
super().__init__(uid, resource, session)
|
|
self.name = resource['Name'] #: str: nazwa szkoły
|
|
self.location = f'{resource["Town"]} {resource["Street"]} {resource["BuildingNumber"]}' #: str: adres szkoły
|
|
|
|
@classmethod
|
|
def create(cls, uid=None, path=('Schools',), session=None, extraction_key='School', expire=timedelta(seconds=1)):
|
|
return super().create(uid, path, session, extraction_key, expire)
|
|
|
|
def __repr__(self):
|
|
return f'<{self.__class__.__name__} {self.name}>'
|
|
|
|
|
|
class SynergiaSubstitution(SynergiaGenericClass):
|
|
def __init__(self, uid, resource, session):
|
|
super().__init__(uid, resource, session)
|
|
|
|
@classmethod
|
|
def create(cls, uid=None, path=('Calendars', 'Substitutions'), session=None, extraction_key='Substitution',
|
|
expire=timedelta(days=7)):
|
|
return super().create(uid, path, session, extraction_key, expire)
|
|
|
|
|
|
class SynergiaRealization(SynergiaGenericClass):
|
|
def __init__(self, uid, resource, session):
|
|
super().__init__(uid, resource, session)
|
|
self.topic = resource['Topic']
|
|
self.date = datetime.strptime(resource['Date'], '%Y-%m-%d')
|
|
self.is_trip = resource['IsTrip']
|
|
self.teaching_program = resource.get('TeachingProgramTopic')
|
|
self.lesson_no = resource['LessonNo']
|
|
self.objects.set_object(
|
|
'teacher', self._json_resource['AddedBy']['Id'], SynergiaTeacher
|
|
).set_object(
|
|
'lesson', resource['Lesson']['Id'], SynergiaLesson
|
|
)
|
|
|
|
@property
|
|
def teacher(self):
|
|
"""
|
|
:rtype: librus_tricks.classes.SynergiaTeacher
|
|
"""
|
|
return self.objects.assembly('teacher')
|
|
|
|
@property
|
|
def lesson(self):
|
|
"""
|
|
:rtype: librus_tricks.classes.SynergiaLesson
|
|
"""
|
|
return self.objects.assembly('lesson')
|
|
|
|
@classmethod
|
|
def create(cls, uid=None, path=('Realizations',), session=None, extraction_key='Realization',
|
|
expire=timedelta(seconds=1)):
|
|
return super().create(uid, path, session, extraction_key, expire)
|
|
|
|
def __repr__(self):
|
|
return f'<{self.__class__.__name__} {self.topic}>'
|