class Addressbook(Serializable): """An address book. :var str ~.id: recipient id :var str ~.login_id: recipient login id :var str ~.first_name: recipient's first name :var str ~.last_name: recipient's last name :var str ~.initials: recipient's initials :var list[Role] ~.roles: recipient's role (eg. Teacher) """ id: str = StringField(key="Id") login_id: int = IntegerField(key="LoginId") first_name: str = StringField(key="Name") last_name: str = StringField(key="Surname") initials: str = StringField(key="Initials") roles: List[Role] = SequenceField(Role, key="Roles", repr=True) @classmethod async def get(cls, api, **kwargs) -> Union[AsyncIterator["Addressbook"], List[int]]: """ :rtype: Union[AsyncIterator[:class:`~vulcan.data.Addressbook`], List[int]] """ data = await api.helper.get_list(DATA_ADDRESSBOOK, FilterType.BY_LOGIN_ID, **kwargs) for addressbook in data: yield Addressbook.load(addressbook)
class Homework(Serializable): """A homework. :var int ~.id: homework's external ID :var str ~.key: homework's key (UUID) :var int ~.homework_id: homework's internal ID :var str ~.content: homework's content :var `~vulcan.hebe.model.DateTime` ~.date_created: homework's creation date :var `~vulcan.hebe.model.Teacher` ~.creator: the teacher who added the homework :var `~vulcan.hebe.model.Subject` ~.subject: the homework's subject :var List[Attachment] ~.attachments: attachments added to homework :var bool ~.is_answer_required: Is an answer required :var `~vulcan.hebe.model.DateTime` ~.deadline: homework's date and time :var `~vulcan.hebe.model.DateTime` ~.answer_deadline: homework's answer deadline :var `~vulcan.hebe.model.DateTime` ~.answer_date: homework's answer date and time """ id: int = IntegerField(key="Id") key: str = StringField(key="Key") homework_id: int = StringField(key="IdHomework") content: str = StringField(key="Content") date_created: DateTime = ChildField(DateTime, key="DateCreated") creator: Teacher = ChildField(Teacher, key="Creator") subject: Subject = ChildField(Subject, key="Subject") attachments: List[Attachment] = SequenceField(Attachment, key="Attachments", repr=True) is_answer_required: Subject = BooleanField(key="IsAnswerRequired") deadline: DateTime = ChildField(DateTime, key="Deadline") answer_deadline: DateTime = ChildField(DateTime, key="AnswerDeadline", required=False) answer_date: DateTime = ChildField(DateTime, key="AnswerDate", required=False) @classmethod async def get(cls, api, last_sync, deleted, **kwargs) -> Union[AsyncIterator["Homework"], List[int]]: """ :rtype: Union[AsyncIterator[:class:`~vulcan.hebe.data.Homework`], List[int]] """ data = await api.helper.get_list(DATA_HOMEWORK, FilterType.BY_PUPIL, deleted=deleted, last_sync=last_sync, **kwargs) for homework in data: yield Homework.load(homework)
class Dictionaries: teachers_json = SequenceField(dict, key="Pracownicy") subjects_json = SequenceField(dict, key="Przedmioty") lesson_times_json = SequenceField(dict, key="PoryLekcji") grade_categories_json = SequenceField(dict, key="KategorieOcen") notice_categories_json = SequenceField(dict, key="KategorieUwag") attendance_categories_json = SequenceField(dict, key="KategorieFrekwencji") attendance_types_json = SequenceField(dict, key="TypyFrekwencji") @property def teachers(self): """List of teachers :rtype: List[:class:`~vulcan._teacher.Teacher`] """ return list(map(lambda j: to_model(Teacher, j), self.teachers_json)) @property def subjects(self): """List of subjects :rtype: List[:class:`~vulcan._subject.Subject`] """ return list(map(lambda j: to_model(Subject, j), self.subjects_json)) @property def lesson_times(self): """List of lesson times :rtype: List[:class:`~vulcan._lesson.LessonTime`] """ return list( map(lambda j: to_model(LessonTime, j), self.lesson_times_json)) @property def grade_categories(self): """List of grade categories :rtype: List[:class:`~vulcan._grade.GradeCategory`] """ return list( map(lambda j: to_model(GradeCategory, j), self.grade_categories_json)) def get_teacher_json(self, _id): return find(self.teachers_json, _id) def get_teacher_by_name_json(self, name): return find(self.teachers_json, name, key="Nazwa") def get_teacher_by_login_id_json(self, _id): return find(self.teachers_json, _id, key="LoginId") def get_subject_json(self, _id): return find(self.subjects_json, _id) def get_lesson_time_json(self, _id): return find(self.lesson_times_json, _id) def get_grade_category_json(self, _id): return find(self.grade_categories_json, _id) def get_notice_category_json(self, _id): return find(self.notice_categories_json, _id) def get_attendance_category_json(self, _id): return find(self.attendance_categories_json, _id) def get_attendance_type_json(self, _id): return find(self.attendance_types_json, _id) @classmethod def get(cls, api): j = api.post("Uczen/Slowniki") data = j.get("Data") for i, teacher in enumerate(data["Pracownicy"]): data["Pracownicy"][i]["Nazwa"] = "{} {}".format( teacher["Imie"], teacher["Nazwisko"]) return to_model(cls, data)
class Student(Serializable): """A student object, along with his school, class and period information :var str ~.symbol: the "partition" symbol - can be a town or county name :var str ~.symbol_code: the school unit code - often a 6 digit number :var `~vulcan.hebe.model.Pupil` ~.pupil: contains the student's IDs, names and email :var `~vulcan.hebe.model.Unit` ~.unit: info about the school unit (e.g. several school buildings) :var `~vulcan.hebe.model.School` ~.school: info about the school (a single building of the unit) :var List[`~vulcan.hebe.model.Period`] ~.periods: a list of the student's school year periods """ symbol: str = StringField(key="TopLevelPartition") symbol_code: str = StringField(key="Partition") pupil: Pupil = ChildField(Pupil, key="Pupil") unit: Unit = ChildField(Unit, key="Unit") school: School = ChildField(School, key="ConstituentUnit") periods: List[Period] = SequenceField(Period, key="Periods") @property def full_name(self) -> str: """Gets the student's full name in "FirstName SecondName LastName" format. :rtype: str """ return " ".join(part for part in [ self.pupil.first_name.strip(), self.pupil.second_name.strip(), self.pupil.last_name.strip(), ] if part) @property def current_period(self) -> Period: """Gets the currently ongoing period of the student. :rtype: :class:`~vulcan.hebe.model.Period` """ return next((period for period in self.periods if period.current), None) def period_by_id(self, period_id: int) -> Period: """Gets a period matching the given period ID. :param int period_id: the period ID to look for :rtype: :class:`~vulcan.hebe.model.Period` """ return next( (period for period in self.periods if period.id == period_id), None) @classmethod async def get(cls, api, **kwargs) -> List["Student"]: """ :rtype: List[:class:`~vulcan.hebe.model.Student`] """ data = await api.get(STUDENT_LIST, **kwargs) return list(Student.load(student) for student in data)
class Document: title = StringField(required=True) version = StringField(required=False) date = DateField(required=False) reference = StringField(required=False) custodian = ChildField(Agent, required=False) preparations = SequenceField(Action, required=False) contributions = SequenceField(Action, required=False) approbations = SequenceField(Action, required=False) issues = SequenceField(Issue, required=False) applicable_documents = SequenceField(LinkedDocument, required=False) reference_documents = SequenceField(LinkedDocument, required=False) title_template = StringField(default="Document about {name}", required=False) def configure_from_project(self, project): self.title = self.title_template.format(name=project.name) @staticmethod def sample(): d = Document("document title") d.version = "1.0" d.reference = "REC-FOO-A" d.custodian = "mister.custodian" d.preparations.append( Action(name='John Doe', role='Leader', description='Preparation of review', date='2019-01-01')) d.contributions = [ Action(name='John Doe', role='Leader', description='Preparation of review', date='2019-01-01'), Action(name='John Doe', role='Leader', description='Preparation of review', date='2019-01-01'), Action(name='John Doe', role='Leader', description='Preparation of review', date='2019-01-01') ] d.approbations.append( Action(name='John Doe', role='Leader', description='Preparation of review', date='2019-01-01')) d.issues = [ Issue( id='0.1', date='2018-11-01', page=["2"], description='Typo', comment= 'file to view the source code until proper documentation is generated.' ), Issue(id='0.2', date='2018-11-01', page=["2"], description='Typo very long', comment='balbalbalbalbalb'), Issue(id='0.3', date='2018-11-01', page=["2", "3"], description='Typo', comment='datetime field formatted using formatter.'), Issue(id='0.4', date='2018-11-01', page=["2"], description='Typo', comment='balbalbalbalbalb'), Issue( id='0.5', date='2018-11-01', page=["2"], description='Typo', comment='Adding your own field types is fairly straightforward ' ), ] return d
class Message: """Message :var int ~.id: Message ID :var int ~.sender_id: Message sender's (teacher) ID :var list ~.recipients: A list of :class:`vulcan._message.MessageRecipient` objects :var str ~.title: Title (subject) of the message :var str ~.content: Message content :var `~vulcan._teacher.Teacher` ~.sender: Sender of the message (teacher) :var `datetime.datetime` ~.sent_datetime: Date with time when the message was sent :var `datetime.date` ~.sent_date: Date when the message was sent :var `datetime.time` ~.sent_time: Time when the message was sent :var `datetime.datetime` ~.read_datetime: Date with time when the message was read, optional :var `datetime.date` ~.read_date: Date when the message was read, optional :var `datetime.time` ~.read_time: Time when the message was read, optional :var bool ~.is_read: Whether the message is read """ id = IntegerField(key="WiadomoscId") sender_id = IntegerField(key="NadawcaId") recipients = SequenceField(MessageRecipient, key="Adresaci") title = StringField(key="Tytul") content = StringField(key="Tresc") sent_date = DateField(key="DataWyslania", formatter="%d.%m.%Y") sent_time = TimeField(key="GodzinaWyslania", formatter="%H:%M") read_date = DateField(key="DataPrzeczytania", formatter="%d.%m.%Y", required=False) read_time = TimeField(key="GodzinaPrzeczytania", formatter="%H:%M", required=False) sender = ChildField(Teacher, required=False) @property def sent_datetime(self): return datetime.combine(self.sent_date, self.sent_time) @property def read_datetime(self): if self.read_date and self.read_time: return datetime.combine(self.read_date, self.read_time) return None @property def is_read(self): return self.read_date is not None @classmethod def get(cls, api, date_from=None, date_to=None): if not date_from: date_from = api.student.period.from_ if not date_to: date_to = api.student.period.to data = { "DataPoczatkowa": date_from.strftime("%Y-%m-%d"), "DataKoncowa": date_to.strftime("%Y-%m-%d"), } j = api.post("Uczen/WiadomosciOdebrane", json=data) messages = j.get("Data", []) for message in messages: message["sender"] = api.dict.get_teacher_by_login_id_json( message["NadawcaId"] ) yield to_model(cls, message) @classmethod def send(cls, api, title, content, teachers): recipients = list() for teacher_repr in teachers: if isinstance(teacher_repr, int) or ( isinstance(teacher_repr, str) and teacher_repr.isnumeric() ): teacher = to_model( Teacher, api.dict.get_teacher_json(int(teacher_repr)) ) elif isinstance(teacher_repr, str): teacher = to_model( Teacher, api.dict.get_teacher_by_name_json(teacher_repr) ) elif isinstance(teacher_repr, dict): teacher = to_model(Teacher, teacher_repr) elif isinstance(teacher_repr, Teacher): teacher = teacher_repr else: continue recipients.append( { "LoginId": teacher.login_id, "Nazwa": teacher.name_reversed, } ) if len(recipients) == 0: raise ValueError("There must be at least 1 correct recipient.") data = { "NadawcaWiadomosci": api.student.account_name, "Tytul": title, "Tresc": content, "Adresaci": recipients, } log.info("Sending a message...") j = api.post("Uczen/DodajWiadomosc", json=data) log.info("Message sent successfully!") return j.get("Data", {}).get("WiadomoscId")