mirror of
https://github.com/ae-utbm/sith.git
synced 2025-12-20 23:03:21 +00:00
rename UV to UE
This commit is contained in:
@@ -1,4 +1,4 @@
|
||||
"""Set of functions to interact with the UTBM UV api."""
|
||||
"""Set of functions to interact with the UTBM UE api."""
|
||||
|
||||
from typing import Iterator
|
||||
|
||||
@@ -6,14 +6,14 @@ import requests
|
||||
from django.conf import settings
|
||||
from django.utils.functional import cached_property
|
||||
|
||||
from pedagogy.schemas import ShortUvList, UtbmFullUvSchema, UtbmShortUvSchema, UvSchema
|
||||
from pedagogy.schemas import ShortUeList, UeSchema, UtbmFullUeSchema, UtbmShortUeSchema
|
||||
|
||||
|
||||
class UtbmApiClient(requests.Session):
|
||||
"""A wrapper around `requests.Session` to perform requests to the UTBM UV API."""
|
||||
"""A wrapper around `requests.Session` to perform requests to the UTBM UE API."""
|
||||
|
||||
BASE_URL = settings.SITH_PEDAGOGY_UTBM_API
|
||||
_cache = {"short_uvs": {}}
|
||||
_cache = {"short_ues": {}}
|
||||
|
||||
@cached_property
|
||||
def current_year(self) -> int:
|
||||
@@ -22,83 +22,83 @@ class UtbmApiClient(requests.Session):
|
||||
response = self.get(url)
|
||||
return response.json()[-1]["annee"]
|
||||
|
||||
def fetch_short_uvs(
|
||||
def fetch_short_ues(
|
||||
self, lang: str = "fr", year: int | None = None
|
||||
) -> list[UtbmShortUvSchema]:
|
||||
"""Get the list of UVs in their short format from the UTBM API"""
|
||||
) -> list[UtbmShortUeSchema]:
|
||||
"""Get the list of UEs in their short format from the UTBM API"""
|
||||
if year is None:
|
||||
year = self.current_year
|
||||
if lang not in self._cache["short_uvs"]:
|
||||
self._cache["short_uvs"][lang] = {}
|
||||
if year not in self._cache["short_uvs"][lang]:
|
||||
if lang not in self._cache["short_ues"]:
|
||||
self._cache["short_ues"][lang] = {}
|
||||
if year not in self._cache["short_ues"][lang]:
|
||||
url = f"{self.BASE_URL}/uvs/{lang}/{year}"
|
||||
response = self.get(url)
|
||||
uvs = ShortUvList.validate_json(response.content)
|
||||
self._cache["short_uvs"][lang][year] = uvs
|
||||
return self._cache["short_uvs"][lang][year]
|
||||
ues = ShortUeList.validate_json(response.content)
|
||||
self._cache["short_ues"][lang][year] = ues
|
||||
return self._cache["short_ues"][lang][year]
|
||||
|
||||
def fetch_uvs(
|
||||
def fetch_ues(
|
||||
self, lang: str = "fr", year: int | None = None
|
||||
) -> Iterator[UvSchema]:
|
||||
"""Fetch all UVs from the UTBM API, parsed in a format that we can use.
|
||||
) -> Iterator[UeSchema]:
|
||||
"""Fetch all UEs from the UTBM API, parsed in a format that we can use.
|
||||
|
||||
Warning:
|
||||
We need infos from the full uv schema, and the UTBM UV API
|
||||
We need infos from the full ue schema, and the UTBM UE API
|
||||
has no route to get all of them at once.
|
||||
We must do one request per UV (for a total of around 730 UVs),
|
||||
We must do one request per UE (for a total of around 730 UEs),
|
||||
which takes a lot of time.
|
||||
Hopefully, there seems to be no rate-limit, so an error
|
||||
in the middle of the process isn't likely to occur.
|
||||
"""
|
||||
if year is None:
|
||||
year = self.current_year
|
||||
shorts_uvs = self.fetch_short_uvs(lang, year)
|
||||
# When UVs are common to multiple branches (like most HUMA)
|
||||
shorts_ues = self.fetch_short_ues(lang, year)
|
||||
# When UEs are common to multiple branches (like most HUMA)
|
||||
# the UTBM API duplicates them for every branch.
|
||||
# We have no way in our db to link a UV to multiple formations,
|
||||
# so we just create a single UV, which formation is the one
|
||||
# of the first UV found in the list.
|
||||
# We have no way in our db to link a UE to multiple formations,
|
||||
# so we just create a single UE, which formation is the one
|
||||
# of the first UE found in the list.
|
||||
# For example, if we have CC01 (TC), CC01 (IMSI) and CC01 (EDIM),
|
||||
# we will only keep CC01 (TC).
|
||||
unique_short_uvs = {}
|
||||
for uv in shorts_uvs:
|
||||
if uv.code not in unique_short_uvs:
|
||||
unique_short_uvs[uv.code] = uv
|
||||
for uv in unique_short_uvs.values():
|
||||
uv_url = f"{self.BASE_URL}/uv/{lang}/{year}/{uv.code}/{uv.code_formation}"
|
||||
response = requests.get(uv_url)
|
||||
full_uv = UtbmFullUvSchema.model_validate_json(response.content)
|
||||
yield make_clean_uv(uv, full_uv)
|
||||
unique_short_ues = {}
|
||||
for ue in shorts_ues:
|
||||
if ue.code not in unique_short_ues:
|
||||
unique_short_ues[ue.code] = ue
|
||||
for ue in unique_short_ues.values():
|
||||
ue_url = f"{self.BASE_URL}/uv/{lang}/{year}/{ue.code}/{ue.code_formation}"
|
||||
response = requests.get(ue_url)
|
||||
full_ue = UtbmFullUeSchema.model_validate_json(response.content)
|
||||
yield make_clean_ue(ue, full_ue)
|
||||
|
||||
def find_uv(self, lang: str, code: str, year: int | None = None) -> UvSchema | None:
|
||||
"""Find an UV from the UTBM API."""
|
||||
# query the UV list
|
||||
def find_uu(self, lang: str, code: str, year: int | None = None) -> UeSchema | None:
|
||||
"""Find an UE from the UTBM API."""
|
||||
# query the UE list
|
||||
if not year:
|
||||
year = self.current_year
|
||||
# the UTBM API has no way to fetch a single short uv,
|
||||
# and short uvs contain infos that we need and are not
|
||||
# in the full uv schema, so we must fetch everything.
|
||||
short_uvs = self.fetch_short_uvs(lang, year)
|
||||
short_uv = next((uv for uv in short_uvs if uv.code == code), None)
|
||||
if short_uv is None:
|
||||
# the UTBM API has no way to fetch a single short ue,
|
||||
# and short ues contain infos that we need and are not
|
||||
# in the full ue schema, so we must fetch everything.
|
||||
short_ues = self.fetch_short_ues(lang, year)
|
||||
short_ue = next((ue for ue in short_ues if ue.code == code), None)
|
||||
if short_ue is None:
|
||||
return None
|
||||
|
||||
# get detailed information about the UV
|
||||
uv_url = f"{self.BASE_URL}/uv/{lang}/{year}/{code}/{short_uv.code_formation}"
|
||||
response = requests.get(uv_url)
|
||||
full_uv = UtbmFullUvSchema.model_validate_json(response.content)
|
||||
return make_clean_uv(short_uv, full_uv)
|
||||
# get detailed information about the UE
|
||||
ue_url = f"{self.BASE_URL}/uv/{lang}/{year}/{code}/{short_ue.code_formation}"
|
||||
response = requests.get(ue_url)
|
||||
full_ue = UtbmFullUeSchema.model_validate_json(response.content)
|
||||
return make_clean_ue(short_ue, full_ue)
|
||||
|
||||
|
||||
def make_clean_uv(short_uv: UtbmShortUvSchema, full_uv: UtbmFullUvSchema) -> UvSchema:
|
||||
def make_clean_ue(short_ue: UtbmShortUeSchema, full_ue: UtbmFullUeSchema) -> UeSchema:
|
||||
"""Cleans the data up so that it corresponds to our data representation.
|
||||
|
||||
Some of the needed information are in the short uv schema, some
|
||||
other in the full uv schema.
|
||||
Some of the needed information are in the short ue schema, some
|
||||
other in the full ue schema.
|
||||
Thus we combine those information to obtain a data schema suitable
|
||||
for our needs.
|
||||
"""
|
||||
if full_uv.departement == "Pôle Humanités":
|
||||
if full_ue.departement == "Pôle Humanités":
|
||||
department = "HUMA"
|
||||
else:
|
||||
department = {
|
||||
@@ -112,9 +112,9 @@ def make_clean_uv(short_uv: UtbmShortUvSchema, full_uv: UtbmFullUvSchema) -> UvS
|
||||
"ED": "EDIM",
|
||||
"AI": "GI",
|
||||
"AM": "MC",
|
||||
}.get(short_uv.code_formation, "NA")
|
||||
}.get(short_ue.code_formation, "NA")
|
||||
|
||||
match short_uv.ouvert_printemps, short_uv.ouvert_automne:
|
||||
match short_ue.ouvert_printemps, short_ue.ouvert_automne:
|
||||
case True, True:
|
||||
semester = "AUTUMN_AND_SPRING"
|
||||
case True, False:
|
||||
@@ -124,22 +124,22 @@ def make_clean_uv(short_uv: UtbmShortUvSchema, full_uv: UtbmFullUvSchema) -> UvS
|
||||
case _:
|
||||
semester = "CLOSED"
|
||||
|
||||
return UvSchema(
|
||||
title=full_uv.libelle or "",
|
||||
code=full_uv.code,
|
||||
credit_type=short_uv.code_categorie or "FREE",
|
||||
return UeSchema(
|
||||
title=full_ue.libelle or "",
|
||||
code=full_ue.code,
|
||||
credit_type=short_ue.code_categorie or "FREE",
|
||||
semester=semester,
|
||||
language=short_uv.code_langue.upper(),
|
||||
credits=full_uv.credits_ects,
|
||||
language=short_ue.code_langue.upper(),
|
||||
credits=full_ue.credits_ects,
|
||||
department=department,
|
||||
hours_THE=next((i.nbh for i in full_uv.activites if i.code == "THE"), 0) // 60,
|
||||
hours_TD=next((i.nbh for i in full_uv.activites if i.code == "TD"), 0) // 60,
|
||||
hours_TP=next((i.nbh for i in full_uv.activites if i.code == "TP"), 0) // 60,
|
||||
hours_TE=next((i.nbh for i in full_uv.activites if i.code == "TE"), 0) // 60,
|
||||
hours_CM=next((i.nbh for i in full_uv.activites if i.code == "CM"), 0) // 60,
|
||||
manager=full_uv.respo_automne or full_uv.respo_printemps or "",
|
||||
objectives=full_uv.objectifs or "",
|
||||
program=full_uv.programme or "",
|
||||
skills=full_uv.acquisition_competences or "",
|
||||
key_concepts=full_uv.acquisition_notions or "",
|
||||
hours_THE=next((i.nbh for i in full_ue.activites if i.code == "THE"), 0) // 60,
|
||||
hours_TD=next((i.nbh for i in full_ue.activites if i.code == "TD"), 0) // 60,
|
||||
hours_TP=next((i.nbh for i in full_ue.activites if i.code == "TP"), 0) // 60,
|
||||
hours_TE=next((i.nbh for i in full_ue.activites if i.code == "TE"), 0) // 60,
|
||||
hours_CM=next((i.nbh for i in full_ue.activites if i.code == "CM"), 0) // 60,
|
||||
manager=full_ue.respo_automne or full_ue.respo_printemps or "",
|
||||
objectives=full_ue.objectifs or "",
|
||||
program=full_ue.programme or "",
|
||||
skills=full_ue.acquisition_competences or "",
|
||||
key_concepts=full_ue.acquisition_notions or "",
|
||||
)
|
||||
|
||||
Reference in New Issue
Block a user