diff --git a/app/__init__.py b/app/__init__.py index d6e0be82f..976908844 100755 --- a/app/__init__.py +++ b/app/__init__.py @@ -28,6 +28,9 @@ from flask_migrate import Migrate from flask_sqlalchemy import SQLAlchemy from jinja2 import select_autoescape +import numpy as np +import psycopg2 +from psycopg2.extensions import AsIs as psycopg2_AsIs import sqlalchemy as sa import werkzeug.debug from wtforms.fields import HiddenField @@ -68,6 +71,19 @@ cache = Cache( ) +# NumPy & Psycopg2 (necessary with Numpy 2.0) +# probablement à changer quand on passera à psycopg3.2 +def adapt_numpy_scalar(numpy_scalar): + """Adapt numeric types for psycopg2""" + return psycopg2_AsIs(numpy_scalar if not np.isnan(numpy_scalar) else "'NaN'") + + +psycopg2.extensions.register_adapter(np.float32, adapt_numpy_scalar) +psycopg2.extensions.register_adapter(np.float64, adapt_numpy_scalar) +psycopg2.extensions.register_adapter(np.int32, adapt_numpy_scalar) +psycopg2.extensions.register_adapter(np.int64, adapt_numpy_scalar) + + def handle_sco_value_error(exc): "page d'erreur avec message" return render_template("sco_value_error.j2", exc=exc), 404 diff --git a/app/but/jury_but.py b/app/but/jury_but.py index 8ccb06d6b..4f3fb5c9c 100644 --- a/app/but/jury_but.py +++ b/app/but/jury_but.py @@ -1557,8 +1557,8 @@ class DecisionsProposeesUE(DecisionsProposees): res: ResultatsSemestreBUT = ( self.rcue.res_pair if paire else self.rcue.res_impair ) - self.moy_ue = np.NaN - self.moy_ue_with_cap = np.NaN + self.moy_ue = np.nan + self.moy_ue_with_cap = np.nan self.ue_status = {} if self.ue.type != sco_codes.UE_STANDARD: diff --git a/app/comp/moy_mod.py b/app/comp/moy_mod.py index 7f33065b1..cfdea10b0 100644 --- a/app/comp/moy_mod.py +++ b/app/comp/moy_mod.py @@ -549,7 +549,7 @@ def load_evaluations_poids(moduleimpl_id: int) -> tuple[pd.DataFrame, list]: EvaluationUEPoids.evaluation ).filter_by(moduleimpl_id=moduleimpl_id): try: - evals_poids[ue_poids.ue_id][ue_poids.evaluation_id] = ue_poids.poids + evals_poids.loc[ue_poids.evaluation_id, ue_poids.ue_id] = ue_poids.poids except KeyError: pass # poids vers des UE qui n'existent plus ou sont dans un autre semestre... @@ -564,7 +564,7 @@ def load_evaluations_poids(moduleimpl_id: int) -> tuple[pd.DataFrame, list]: if np.isnan(evals_poids.values.flat).any(): ue_coefs = modimpl.module.get_ue_coef_dict() for ue in ues: - evals_poids[ue.id][evals_poids[ue.id].isna()] = ( + evals_poids.loc[evals_poids[ue.id].isna(), ue.id] = ( 1 if ue_coefs.get(ue.id, default_poids) > 0 else 0 ) diff --git a/app/comp/moy_sem.py b/app/comp/moy_sem.py index 20d9752ce..540b78668 100644 --- a/app/comp/moy_sem.py +++ b/app/comp/moy_sem.py @@ -82,7 +82,7 @@ def compute_sem_moys_apc_using_ects( moy_gen = (etud_moy_ue_df * ects).sum(axis=1) / ects.sum(axis=1) except ZeroDivisionError: # peut arriver si aucun module... on ignore - moy_gen = pd.Series(np.NaN, index=etud_moy_ue_df.index) + moy_gen = pd.Series(np.nan, index=etud_moy_ue_df.index) except TypeError: if None in ects: formation = db.session.get(Formation, formation_id) @@ -93,7 +93,7 @@ def compute_sem_moys_apc_using_ects( scodoc_dept=g.scodoc_dept, formation_id=formation_id)}">{formation.get_titre_version()})""" ) ) - moy_gen = pd.Series(np.NaN, index=etud_moy_ue_df.index) + moy_gen = pd.Series(np.nan, index=etud_moy_ue_df.index) else: raise return moy_gen diff --git a/app/comp/moy_ue.py b/app/comp/moy_ue.py index 24fdbd468..5e88f29e3 100644 --- a/app/comp/moy_ue.py +++ b/app/comp/moy_ue.py @@ -139,9 +139,9 @@ def df_load_modimpl_coefs( for mod_coef in mod_coefs: try: - modimpl_coefs_df[mod2impl[mod_coef.module_id]][ - mod_coef.ue_id - ] = mod_coef.coef + modimpl_coefs_df.loc[mod_coef.ue_id, mod2impl[mod_coef.module_id]] = ( + mod_coef.coef + ) except IndexError: # il peut y avoir en base des coefs sur des modules ou UE # qui ont depuis été retirés de la formation diff --git a/app/pe/moys/pe_sxtag.py b/app/pe/moys/pe_sxtag.py index 6ddb1ee9f..6b148cf53 100644 --- a/app/pe/moys/pe_sxtag.py +++ b/app/pe/moys/pe_sxtag.py @@ -333,7 +333,7 @@ class SxTag(pe_tabletags.TableTag): etud_moy = np.max(set_cube_no_nan, axis=2) # Fix les max non calculé -1 -> NaN - etud_moy[etud_moy < 0] = np.NaN + etud_moy[etud_moy < 0] = np.nan # Le dataFrame etud_moy_tag_df = pd.DataFrame( diff --git a/requirements-3.11.txt b/requirements-3.11.txt index e50f0cb71..825c16351 100644 --- a/requirements-3.11.txt +++ b/requirements-3.11.txt @@ -1,114 +1,116 @@ -alembic==1.13.0 -astroid==3.0.1 +alembic==1.13.2 +astroid==3.2.4 async-timeout==4.0.3 -attrs==23.1.0 -Babel==2.13.1 -black==23.11.0 -blinker==1.7.0 +attrs==23.2.0 +Babel==2.15.0 +black==24.4.2 +blinker==1.8.2 Brotli==1.1.0 cachelib==0.9.0 -certifi==2023.11.17 +certifi==2024.7.4 cffi==1.16.0 chardet==5.2.0 charset-normalizer==3.3.2 click==8.1.7 cracklib==2.9.6 -cryptography==41.0.7 +cryptography==43.0.0 cssselect2==0.7.0 +deepdiff==6.7.1 Deprecated==1.2.14 -dill==0.3.7 -dnspython==2.4.2 -dominate==2.9.0 -email-validator==2.1.0.post1 +dill==0.3.8 +dnspython==2.6.1 +dominate==2.9.1 +email_validator==2.2.0 ERAlchemy==1.2.10 et-xmlfile==1.1.0 -exceptiongroup==1.2.0 -execnet==2.0.2 -flake8==6.1.0 -Flask==3.0.0 +exceptiongroup==1.2.2 +execnet==2.1.1 +flake8==7.1.0 +Flask==3.0.3 flask-babel==4.0.0 -Flask-Caching==2.1.0 +Flask-Caching==2.3.0 Flask-HTTPAuth==4.8.0 Flask-JSON==0.4.0 Flask-Login==0.6.3 -Flask-Mail==0.9.1 -Flask-Migrate==4.0.5 +Flask-Mail==0.10.0 +Flask-Migrate==4.0.7 Flask-SQLAlchemy==3.1.1 Flask-WTF==1.2.1 -fonttools==4.46.0 -gprof2dot==2022.7.29 -greenlet==3.0.1 -gunicorn==21.2.0 +fonttools==4.53.1 +gprof2dot==2024.6.6 +greenlet==3.0.3 +gunicorn==22.0.0 html5lib==1.1 -icalendar==5.0.11 -idna==3.6 -importlib-metadata==7.0.0 +icalendar==5.0.13 +idna==3.7 +importlib_metadata==8.2.0 iniconfig==2.0.0 -isort==5.12.0 -itsdangerous==2.1.2 -Jinja2==3.1.2 -lazy-object-proxy==1.9.0 -lxml==4.9.3 -Mako==1.3.0 -MarkupSafe==2.1.3 +isort==5.13.2 +itsdangerous==2.2.0 +Jinja2==3.1.4 +lazy-object-proxy==1.10.0 +lxml==5.2.2 +Mako==1.3.5 +MarkupSafe==2.1.5 mccabe==0.7.0 -mypy==1.7.1 +mypy==1.11.0 mypy-extensions==1.0.0 -numpy==1.26.2 -openpyxl==3.1.2 -packaging==23.2 -pandas==2.1.3 -pathspec==0.11.2 -Pillow==10.1.0 -platformdirs==4.1.0 -pluggy==1.3.0 +numpy==2.0.1 +openpyxl==3.1.5 +ordered-set==4.1.0 +packaging==24.1 +pandas==2.2.2 +pathspec==0.12.1 +pillow==10.4.0 +platformdirs==4.2.2 +pluggy==1.5.0 psycopg2==2.9.9 -puremagic==1.15 +puremagic==1.26 py==1.11.0 -pycodestyle==2.11.1 -pycparser==2.21 -pydot==1.4.2 -pydyf==0.8.0 -pyflakes==3.1.0 -pygraphviz==1.11 +pycodestyle==2.12.0 +pycparser==2.22 +pydot==3.0.1 +pydyf==0.11.0 +pyflakes==3.2.0 +pygraphviz==1.13 PyJWT==2.8.0 -pylint==3.0.2 +pylint==3.2.6 pylint-flask==0.6 pylint-flask-sqlalchemy==0.2.0 pylint-plugin-utils==0.8.2 -pyOpenSSL==23.3.0 -pyparsing==3.1.1 -pyphen==0.14.0 -pytest==7.4.3 -pytest-xdist==3.5.0 -python-dateutil==2.8.2 -python-docx==1.1.0 -python-dotenv==1.0.0 +pyOpenSSL==24.2.1 +pyparsing==3.1.2 +pyphen==0.16.0 +pytest==8.3.2 +pytest-xdist==3.6.1 +python-dateutil==2.9.0.post0 +python-docx==1.1.2 +python-dotenv==1.0.1 python-editor==1.0.4 -pytz==2023.3.post1 +pytz==2024.1 PyYAML==6.0.1 -redis==5.0.1 -reportlab==4.0.7 -requests==2.31.0 -rq==1.15.1 +redis==5.0.8 +reportlab==4.2.2 +requests==2.32.3 +rq==1.16.2 six==1.16.0 snakeviz==2.2.0 -SQLAlchemy==2.0.23 -tinycss2==1.2.1 +SQLAlchemy==2.0.31 +tinycss2==1.3.0 toml==0.10.2 tomli==2.0.1 -tomlkit==0.12.3 -tornado==6.4 +tomlkit==0.13.0 +tornado==6.4.1 tuna==0.5.11 -typing_extensions==4.8.0 -tzdata==2023.3 -urllib3==2.1.0 +typing_extensions==4.12.2 +tzdata==2024.1 +urllib3==2.2.2 visitor==0.1.3 -weasyprint==60.1 +weasyprint==62.3 webencodings==0.5.1 -Werkzeug==3.0.1 +Werkzeug==3.0.3 wrapt==1.16.0 -WTForms==3.1.1 +WTForms==3.1.2 xmltodict==0.13.0 -zipp==3.17.0 +zipp==3.19.2 zopfli==0.2.3