diff --git a/collectives/api/event.py b/collectives/api/event.py index b728e759..aac3a38c 100644 --- a/collectives/api/event.py +++ b/collectives/api/event.py @@ -1,7 +1,7 @@ """API to get the event list in index page.""" import json -from datetime import datetime, timedelta +from datetime import timedelta from flask import url_for, request, abort from flask_login import current_user @@ -15,7 +15,7 @@ from collectives.models import Question, QuestionAnswer, Configuration from collectives.utils.url import slugify from collectives.utils.access import valid_user -from collectives.utils.time import format_datetime_range, parse_api_date +from collectives.utils.time import format_datetime_range, parse_api_date, current_time def photo_uri(event): @@ -266,7 +266,7 @@ def events(): # Hide very old events to unauthenticated if not current_user.is_authenticated: - min_date = datetime.now() - timedelta( + min_date = current_time() - timedelta( days=Configuration.MAX_HISTORY_FOR_ANONYMOUS ) query = query.filter(Event.end > min_date) diff --git a/collectives/forms/reservation.py b/collectives/forms/reservation.py index 78089ab2..feb8756a 100644 --- a/collectives/forms/reservation.py +++ b/collectives/forms/reservation.py @@ -1,12 +1,12 @@ """Module for equipment reservation forms""" -from datetime import datetime from wtforms import SubmitField, HiddenField from flask_wtf.form import FlaskForm from wtforms_alchemy import ModelForm from collectives.models import Reservation +from collectives.utils.time import current_time class ReservationForm(FlaskForm, ModelForm): @@ -27,7 +27,7 @@ def __init__(self, *args, **kwargs): self.event = kwargs["event"] self.collect_date.data = self.event.start else: - self.collect_date.data = datetime.now() + self.collect_date.data = current_time() class LeaderReservationForm(ReservationForm): diff --git a/collectives/routes/auth/signup.py b/collectives/routes/auth/signup.py index fa466f7e..d9b7e298 100644 --- a/collectives/routes/auth/signup.py +++ b/collectives/routes/auth/signup.py @@ -1,7 +1,5 @@ """Auth login to perform account creation and recover.""" -import datetime - from flask import flash, render_template, redirect, url_for, request from flask import current_app from flask_login import current_user @@ -60,7 +58,7 @@ def process_confirmation(token_uuid): and token.existing_user.type == UserType.UnverifiedLocal ): token.existing_user.type = UserType.Local - token.existing_user.legal_text_signature_date = datetime.datetime.now() + token.existing_user.legal_text_signature_date = current_time() token.existing_user.legal_text_signed_version = ( Configuration.CURRENT_LEGAL_TEXT_VERSION ) diff --git a/collectives/routes/event.py b/collectives/routes/event.py index 5bc03d17..25e89542 100644 --- a/collectives/routes/event.py +++ b/collectives/routes/event.py @@ -5,7 +5,7 @@ # pylint: disable=too-many-lines from typing import Tuple, List, Set -from datetime import datetime, timedelta +from datetime import timedelta import builtins from flask import flash, render_template, redirect, url_for, request, send_file @@ -1213,7 +1213,7 @@ def preview(event_id): if event is None: abort(404) - min_date = datetime.now() - timedelta(days=Configuration.MAX_HISTORY_FOR_ANONYMOUS) + min_date = current_time() - timedelta(days=Configuration.MAX_HISTORY_FOR_ANONYMOUS) if event.end < min_date: abort(404) diff --git a/collectives/routes/profile.py b/collectives/routes/profile.py index 059fd7b7..f66a4ad3 100644 --- a/collectives/routes/profile.py +++ b/collectives/routes/profile.py @@ -3,7 +3,7 @@ This modules contains the /profile Blueprint """ -from datetime import date, datetime +from datetime import date from os.path import exists from io import BytesIO import textwrap @@ -29,6 +29,7 @@ from collectives.utils.access import valid_user from collectives.utils.extranet import ExtranetError from collectives.utils.misc import sanitize_file_name +from collectives.utils.time import current_time images = Images() @@ -205,7 +206,7 @@ def confidentiality_agreement(): request.method == "POST" and current_user.confidentiality_agreement_signature_date == None ): - current_user.confidentiality_agreement_signature_date = datetime.now() + current_user.confidentiality_agreement_signature_date = current_time() db.session.add(current_user) db.session.commit() flash("Merci d'avoir signé la charte RGPD", "success") diff --git a/collectives/utils/extranet.py b/collectives/utils/extranet.py index c86dce88..a54139f9 100644 --- a/collectives/utils/extranet.py +++ b/collectives/utils/extranet.py @@ -201,7 +201,7 @@ def check_license(self, license_number: str) -> LicenseInfo: if self.disabled(): # Dev mode, every license is valid info.exists = True - info.renewal_date = datetime.now() + info.renewal_date = current_time() return info try: diff --git a/collectives/utils/init.py b/collectives/utils/init.py index be9a6971..865eab6f 100644 --- a/collectives/utils/init.py +++ b/collectives/utils/init.py @@ -1,7 +1,6 @@ """Module to initialise DB""" import sqlite3 -import datetime import uuid import sys @@ -12,6 +11,7 @@ from collectives.models import ActivityType, EventType, User, Role, db, RoleIds from collectives.models import Configuration, ConfigurationTypeEnum, ConfigurationItem +from collectives.utils.time import current_time def catch_db_errors(fct, app, *args, **kwargs): @@ -133,10 +133,10 @@ def init_admin(app): user.license = str(uuid.uuid4())[:12] user.first_name = "Compte" user.last_name = "Administrateur" - user.confidentiality_agreement_signature_date = datetime.datetime.now() + user.confidentiality_agreement_signature_date = current_time() version = Configuration.CURRENT_LEGAL_TEXT_VERSION user.legal_text_signed_version = version - user.legal_text_signature_date = datetime.datetime.now() + user.legal_text_signature_date = current_time() user.password = app.config["ADMINPWD"] admin_role = Role(user=user, role_id=int(RoleIds.Administrator)) user.roles.append(admin_role) diff --git a/collectives/utils/stats.py b/collectives/utils/stats.py index cb3d5026..30fef873 100644 --- a/collectives/utils/stats.py +++ b/collectives/utils/stats.py @@ -16,6 +16,7 @@ from collectives.models import RegistrationStatus, EventStatus, ActivityType from collectives.models import User, EventTag from collectives.utils.openpyxl import columns_best_fit +from collectives.utils.time import current_time # Pylint does not understand that func.count IS callable. # See https://github.com/pylint-dev/pylint/issues/1682 @@ -223,7 +224,7 @@ def __init__(self, **kwargs) -> None: self.start = datetime(int(kwargs["year"]), 9, 1, 0, 0, 0) self.end = datetime(int(kwargs["year"]) + 1, 8, 30, 23, 59) - self.creation_time = datetime.now() + self.creation_time = current_time() def nb_days(self) -> int: """Returns number of days during the Engine interval. @@ -482,7 +483,7 @@ def nb_unregistrations_inc_late_and_unjustified_absentees_per_week(self) -> dict ] ), Event.start < func.now(), - Event.start >= datetime.now() - timedelta(weeks=52), + Event.start >= current_time() - timedelta(weeks=52), ) .group_by("event_week", Registration.status) ) diff --git a/tests/events/test_event.py b/tests/events/test_event.py index f11ca4ed..d7eba29f 100644 --- a/tests/events/test_event.py +++ b/tests/events/test_event.py @@ -10,6 +10,7 @@ from collectives.models import db, EventStatus, ActivityType, Event, EventVisibility from collectives.models import RoleIds, Question, QuestionType, RegistrationStatus +from collectives.utils.time import current_time from tests import utils from tests.fixtures.user import promote_user @@ -195,7 +196,7 @@ def test_event_creation(leader_client): response = leader_client.get("/collectives/add") assert response.status_code == 200 - now = datetime.now() + now = current_time() alpinisme = ActivityType.query.filter_by(name="Alpinisme").first() data = { "update_activity": "0", @@ -294,7 +295,7 @@ def test_event_duplication(leader_client, paying_event): assert response.status_code == 200 data = utils.load_data_from_form(response.text, "form_edit_event") - now = datetime.now() + now = current_time() data["start"] = (now + timedelta(days=33)).strftime("%Y-%m-%d %X") data["end"] = (now + timedelta(days=33, hours=3)).strftime("%Y-%m-%d %X") response = leader_client.post("/collectives/add", data=data) @@ -433,7 +434,7 @@ def test_update_attendance_upcoming_event( """Test leader changing status of registrations for an event that starts soon""" event = event1_with_reg_waiting_list - event.start = datetime.now() + timedelta(hours=1) + event.start = current_time() + timedelta(hours=1) db.session.commit() waiting_reg = event.waiting_registrations()[0] diff --git a/tests/events/test_registrations.py b/tests/events/test_registrations.py index ad3eb43a..8e305176 100644 --- a/tests/events/test_registrations.py +++ b/tests/events/test_registrations.py @@ -1,7 +1,8 @@ """Event actions tests related to registrations""" -from datetime import date, timedelta, datetime +from datetime import date, timedelta from collectives.models import db, RegistrationStatus, BadgeIds +from collectives.utils.time import current_time # pylint: disable=unused-argument @@ -526,7 +527,7 @@ def test_register_for_valid_suspended_user( assert user.has_a_valid_badge([BadgeIds.Suspended]) assert user.has_a_valid_suspended_badge() assert len(event.registrations) == 6 - assert not event.can_self_register(user, datetime.now()) + assert not event.can_self_register(user, current_time()) response = user_client.post( f"/collectives/{event.id}/self_register", follow_redirects=True diff --git a/tests/fixtures/event.py b/tests/fixtures/event.py index 55320e19..235000f7 100644 --- a/tests/fixtures/event.py +++ b/tests/fixtures/event.py @@ -1,6 +1,6 @@ """Module to create fixture events.""" -from datetime import date, timedelta, datetime +from datetime import date, timedelta from functools import wraps import pytest @@ -9,6 +9,7 @@ from collectives.models import EventType, Event, EventTag, EventStatus, EventVisibility from collectives.models import Registration, RegistrationLevels, RegistrationStatus from collectives.models import Question, QuestionType, QuestionAnswer +from collectives.utils.time import current_time from tests.fixtures import payment @@ -298,13 +299,13 @@ def event_in_less_than_x_hours_with_reg( """ prototype_event_in_less_than_x_hours.registration_open_time = ( - datetime.now() - timedelta(hours=10) + current_time() - timedelta(hours=10) ) prototype_event_in_less_than_x_hours.registration_close_time = ( - datetime.now() + timedelta(hours=2) + current_time() + timedelta(hours=2) ) - prototype_event_in_less_than_x_hours.start = datetime.now() + timedelta(hours=3) - prototype_event_in_less_than_x_hours.end = datetime.now() + timedelta(hours=4) + prototype_event_in_less_than_x_hours.start = current_time() + timedelta(hours=3) + prototype_event_in_less_than_x_hours.end = current_time() + timedelta(hours=4) prototype_event_in_less_than_x_hours.num_online_slots = 9 for user in [ @@ -321,7 +322,7 @@ def event_in_less_than_x_hours_with_reg( status=RegistrationStatus.Active, level=RegistrationLevels.Normal, is_self=True, - registration_time=datetime.now() - timedelta(weeks=1), + registration_time=current_time() - timedelta(weeks=1), ) ) @@ -336,13 +337,13 @@ def event_in_less_than_x_hours(prototype_event_in_less_than_x_hours): """Fixture for an event starting in less than 48 hours (parameterized).""" prototype_event_in_less_than_x_hours.registration_open_time = ( - datetime.now() - timedelta(hours=10) + current_time() - timedelta(hours=10) ) prototype_event_in_less_than_x_hours.registration_close_time = ( - datetime.now() + timedelta(hours=2) + current_time() + timedelta(hours=2) ) - prototype_event_in_less_than_x_hours.start = datetime.now() + timedelta(hours=3) - prototype_event_in_less_than_x_hours.end = datetime.now() + timedelta(hours=4) + prototype_event_in_less_than_x_hours.start = current_time() + timedelta(hours=3) + prototype_event_in_less_than_x_hours.end = current_time() + timedelta(hours=4) prototype_event_in_less_than_x_hours.num_online_slots = 9 @@ -364,13 +365,13 @@ def event_with_no_activity_type_in_less_than_x_hours_with_reg( """ prototype_event_in_less_than_x_hours.registration_open_time = ( - datetime.now() - timedelta(hours=10) + current_time() - timedelta(hours=10) ) prototype_event_in_less_than_x_hours.registration_close_time = ( - datetime.now() + timedelta(hours=2) + current_time() + timedelta(hours=2) ) - prototype_event_in_less_than_x_hours.start = datetime.now() + timedelta(hours=3) - prototype_event_in_less_than_x_hours.end = datetime.now() + timedelta(hours=4) + prototype_event_in_less_than_x_hours.start = current_time() + timedelta(hours=3) + prototype_event_in_less_than_x_hours.end = current_time() + timedelta(hours=4) prototype_event_in_less_than_x_hours.num_online_slots = 9 prototype_event_in_less_than_x_hours.num_online_slots = 9 diff --git a/tests/fixtures/payment.py b/tests/fixtures/payment.py index 64d7ad43..b73415ba 100644 --- a/tests/fixtures/payment.py +++ b/tests/fixtures/payment.py @@ -2,9 +2,8 @@ These are not pytest fixtures.""" -from datetime import datetime - from collectives.models.payment import ItemPrice, PaymentItem +from collectives.utils.time import current_time def regular_price(): @@ -13,7 +12,7 @@ def regular_price(): price.amount = 12.5 price.title = "Normal" price.enabled = True - price.update_time = datetime.now() + price.update_time = current_time() return price @@ -27,7 +26,7 @@ def leader_price(item): # pylint: disable=protected-access price._deprecated_leader_only = True # Test migration as well # pylint: enable=protected-access - price.update_time = datetime.now() + price.update_time = current_time() return price @@ -37,7 +36,7 @@ def free_price(): price.amount = 0 price.title = "Gratuit" price.enabled = True - price.update_time = datetime.now() + price.update_time = current_time() return price @@ -47,7 +46,7 @@ def disabled_price(): price.amount = 0.01 price.title = "Test" price.enabled = False - price.update_time = datetime.now() + price.update_time = current_time() return price diff --git a/tests/fixtures/user.py b/tests/fixtures/user.py index 4dc552e1..e21fd63c 100644 --- a/tests/fixtures/user.py +++ b/tests/fixtures/user.py @@ -1,12 +1,13 @@ """Module to create fixture users.""" from functools import wraps -from datetime import date, datetime, timedelta +from datetime import date, timedelta import pytest from collectives.models import User, Gender, db, Role, RoleIds, ActivityType from collectives.models import Badge, BadgeIds, UserType +from collectives.utils.time import current_time # pylint: disable=unused-argument,redefined-outer-name, unused-import @@ -74,7 +75,7 @@ def user(app): user.phone = f"0601020{identifier:03d}" user.emergency_contact_name = f"Emergency {identifier}" user.emergency_contact_phone = f"0699999{identifier:03}" - user.legal_text_signature_date = datetime.now() + user.legal_text_signature_date = current_time() user.legal_text_signed_version = 1 user.gender = Gender(identifier % 2 + 1) @@ -274,7 +275,7 @@ def promote_user( activity_type = ActivityType.query.filter_by(name=activity_name).first() role.activity_id = activity_type.id if confidentiality_agreement_signature: - user.confidentiality_agreement_signature_date = datetime.now() + user.confidentiality_agreement_signature_date = current_time() db.session.add(role) diff --git a/tests/test_stats.py b/tests/test_stats.py index 6da9ff45..680e0422 100644 --- a/tests/test_stats.py +++ b/tests/test_stats.py @@ -2,11 +2,12 @@ # pylint: disable=unused-argument -from datetime import datetime, timedelta +from datetime import timedelta import openpyxl from collectives.utils.stats import StatisticsEngine +from collectives.utils.time import current_time from collectives.models import ActivityType @@ -47,7 +48,7 @@ def test_statistics_engine_all(stats_env, leader2_user): def test_statistics_engine_from_now(stats_env, leader2_user): """Tests statistics engine on future events.""" engine = StatisticsEngine( - start=datetime.now(), end=datetime.now() + timedelta(days=365) + start=current_time(), end=current_time() + timedelta(days=365) ) assert engine.nb_events() == 5 assert engine.nb_registrations() == 5 diff --git a/tests/unit/test_event.py b/tests/unit/test_event.py index 14832c58..d0623e4b 100644 --- a/tests/unit/test_event.py +++ b/tests/unit/test_event.py @@ -9,6 +9,7 @@ from collectives.models.user_group import UserGroup, GroupRoleCondition from collectives.routes.event import update_waiting_list +from collectives.utils.time import current_time from tests.fixtures.user import promote_to_leader @@ -51,16 +52,16 @@ def test_event_validity(event1, user1, user2): assert event.is_valid() # Test dates - event.end = datetime.datetime.now() + event.end = current_time() assert not event.is_valid() event.end = event.start assert event.is_valid() event.num_online_slots = 1 - event.registration_open_time = datetime.datetime.now() - event.registration_close_time = datetime.datetime.now() + datetime.timedelta(days=1) + event.registration_open_time = current_time() + event.registration_close_time = current_time() + datetime.timedelta(days=1) - assert event.is_registration_open_at_time(datetime.datetime.now()) + assert event.is_registration_open_at_time(current_time()) event.registration_open_time = event.registration_close_time + datetime.timedelta( hours=1 @@ -78,7 +79,7 @@ def test_event_validity(event1, user1, user2): assert not event.opens_before_ends() assert not event.is_valid() - assert not event.is_registration_open_at_time(datetime.datetime.now()) + assert not event.is_registration_open_at_time(current_time()) def test_add_registration(event1, user1, user2): @@ -86,20 +87,20 @@ def test_add_registration(event1, user1, user2): def make_registration(user): """Utility func to create a registration for the given user""" - datetime.datetime.timestamp(datetime.datetime.now()) + datetime.datetime.timestamp(current_time()) return Registration( user=user, status=RegistrationStatus.Active, level=RegistrationLevels.Normal ) event = event1 event.num_online_slots = 2 - event.registration_open_time = datetime.datetime.now() - event.registration_close_time = datetime.datetime.now() + datetime.timedelta(days=1) + event.registration_open_time = current_time() + event.registration_close_time = current_time() + datetime.timedelta(days=1) db.session.add(event) db.session.commit() - now = datetime.datetime.now() + now = current_time() assert event.is_registration_open_at_time(now) assert event.has_free_online_slots() @@ -161,17 +162,13 @@ def test_waiting_list_update(event1: Event, event2: Event, user1: User, user2: U event1.num_online_slots = 1 event1.num_waiting_list = 2 - event1.registration_open_time = datetime.datetime.now() - event1.registration_close_time = datetime.datetime.now() + datetime.timedelta( - days=1 - ) + event1.registration_open_time = current_time() + event1.registration_close_time = current_time() + datetime.timedelta(days=1) event2.num_online_slots = 1 event2.num_waiting_list = 2 - event2.registration_open_time = datetime.datetime.now() - event2.registration_close_time = datetime.datetime.now() + datetime.timedelta( - days=1 - ) + event2.registration_open_time = current_time() + event2.registration_close_time = current_time() + datetime.timedelta(days=1) def make_registration(event, user, status): """Utility func to create a registration for the given user""" @@ -233,10 +230,8 @@ def test_paying_event_waiting_list_update( paying_event.num_online_slots = 1 paying_event.num_waiting_list = 2 - paying_event.registration_open_time = datetime.datetime.now() - paying_event.registration_close_time = datetime.datetime.now() + datetime.timedelta( - days=1 - ) + paying_event.registration_open_time = current_time() + paying_event.registration_close_time = current_time() + datetime.timedelta(days=1) def make_waiting_registration(event, user): """Utility func to create a registration for the given user"""