mirror of
https://github.com/ae-utbm/sith.git
synced 2026-09-09 14:04:36 +00:00
Compare commits
1
Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
111fca85db |
+1
-1
@@ -1 +1 @@
|
|||||||
3.14
|
3.12
|
||||||
+2
-6
@@ -1,15 +1,11 @@
|
|||||||
from typing import TYPE_CHECKING
|
|
||||||
|
|
||||||
from django.contrib import admin, messages
|
from django.contrib import admin, messages
|
||||||
|
from django.db.models import QuerySet
|
||||||
|
from django.http import HttpRequest
|
||||||
from django.utils.translation import gettext_lazy as _
|
from django.utils.translation import gettext_lazy as _
|
||||||
|
|
||||||
from api.hashers import generate_key
|
from api.hashers import generate_key
|
||||||
from api.models import ApiClient, ApiKey
|
from api.models import ApiClient, ApiKey
|
||||||
|
|
||||||
if TYPE_CHECKING:
|
|
||||||
from django.db.models import QuerySet
|
|
||||||
from django.http import HttpRequest
|
|
||||||
|
|
||||||
|
|
||||||
@admin.register(ApiClient)
|
@admin.register(ApiClient)
|
||||||
class ApiClientAdmin(admin.ModelAdmin):
|
class ApiClientAdmin(admin.ModelAdmin):
|
||||||
|
|||||||
+1
-5
@@ -1,13 +1,9 @@
|
|||||||
from typing import TYPE_CHECKING
|
from django.http import HttpRequest
|
||||||
|
|
||||||
from ninja.security import APIKeyHeader
|
from ninja.security import APIKeyHeader
|
||||||
|
|
||||||
from api.hashers import get_hasher
|
from api.hashers import get_hasher
|
||||||
from api.models import ApiClient, ApiKey
|
from api.models import ApiClient, ApiKey
|
||||||
|
|
||||||
if TYPE_CHECKING:
|
|
||||||
from django.http import HttpRequest
|
|
||||||
|
|
||||||
|
|
||||||
class ApiKeyAuth(APIKeyHeader):
|
class ApiKeyAuth(APIKeyHeader):
|
||||||
"""Authentication through client api keys."""
|
"""Authentication through client api keys."""
|
||||||
|
|||||||
+4
-6
@@ -39,16 +39,14 @@ Example:
|
|||||||
|
|
||||||
import operator
|
import operator
|
||||||
from functools import reduce
|
from functools import reduce
|
||||||
from typing import TYPE_CHECKING, Any, Callable
|
from typing import Any, Callable
|
||||||
|
|
||||||
from ninja_extra.permissions import BasePermission
|
|
||||||
|
|
||||||
from counter.utils import is_logged_in_counter
|
|
||||||
|
|
||||||
if TYPE_CHECKING:
|
|
||||||
from django.contrib.auth.models import Permission
|
from django.contrib.auth.models import Permission
|
||||||
from django.http import HttpRequest
|
from django.http import HttpRequest
|
||||||
from ninja_extra import ControllerBase
|
from ninja_extra import ControllerBase
|
||||||
|
from ninja_extra.permissions import BasePermission
|
||||||
|
|
||||||
|
from counter.utils import is_logged_in_counter
|
||||||
|
|
||||||
|
|
||||||
class IsInGroup(BasePermission):
|
class IsInGroup(BasePermission):
|
||||||
|
|||||||
+2
-6
@@ -12,16 +12,12 @@
|
|||||||
# OR WITHIN THE LOCAL FILE "LICENSE"
|
# OR WITHIN THE LOCAL FILE "LICENSE"
|
||||||
#
|
#
|
||||||
#
|
#
|
||||||
from typing import TYPE_CHECKING
|
|
||||||
|
|
||||||
from django.contrib import admin
|
from django.contrib import admin
|
||||||
|
|
||||||
from club.models import Club, ClubLink, ClubRole, LinkType, Membership
|
|
||||||
|
|
||||||
if TYPE_CHECKING:
|
|
||||||
from django.forms.models import ModelForm
|
from django.forms.models import ModelForm
|
||||||
from django.http import HttpRequest
|
from django.http import HttpRequest
|
||||||
|
|
||||||
|
from club.models import Club, ClubLink, ClubRole, LinkType, Membership
|
||||||
|
|
||||||
|
|
||||||
@admin.register(Club)
|
@admin.register(Club)
|
||||||
class ClubAdmin(admin.ModelAdmin):
|
class ClubAdmin(admin.ModelAdmin):
|
||||||
|
|||||||
@@ -1,16 +1,12 @@
|
|||||||
# Generated by Django 4.2.16 on 2024-11-20 17:08
|
# Generated by Django 4.2.16 on 2024-11-20 17:08
|
||||||
|
|
||||||
from typing import TYPE_CHECKING
|
|
||||||
|
|
||||||
import django.db.models.deletion
|
import django.db.models.deletion
|
||||||
import django.db.models.functions.datetime
|
import django.db.models.functions.datetime
|
||||||
from django.db import migrations, models
|
from django.db import migrations, models
|
||||||
|
from django.db.migrations.state import StateApps
|
||||||
from django.db.models import Q
|
from django.db.models import Q
|
||||||
from django.utils.timezone import localdate
|
from django.utils.timezone import localdate
|
||||||
|
|
||||||
if TYPE_CHECKING:
|
|
||||||
from django.db.migrations.state import StateApps
|
|
||||||
|
|
||||||
# Before the club role rework, the maximum free role
|
# Before the club role rework, the maximum free role
|
||||||
# was the hardcoded highest non-board role
|
# was the hardcoded highest non-board role
|
||||||
MAXIMUM_FREE_ROLE = 1
|
MAXIMUM_FREE_ROLE = 1
|
||||||
|
|||||||
@@ -1,13 +1,9 @@
|
|||||||
# Generated by Django 5.2.3 on 2025-06-21 21:59
|
# Generated by Django 5.2.3 on 2025-06-21 21:59
|
||||||
|
|
||||||
from typing import TYPE_CHECKING
|
|
||||||
|
|
||||||
import django.db.models.deletion
|
import django.db.models.deletion
|
||||||
from django.db import migrations, models
|
from django.db import migrations, models
|
||||||
from django.db.models import Case, When
|
|
||||||
|
|
||||||
if TYPE_CHECKING:
|
|
||||||
from django.db.migrations.state import StateApps
|
from django.db.migrations.state import StateApps
|
||||||
|
from django.db.models import Case, When
|
||||||
|
|
||||||
PRESIDENCY_ROLES = [10, 9]
|
PRESIDENCY_ROLES = [10, 9]
|
||||||
MAXIMUM_FREE_ROLE = 1
|
MAXIMUM_FREE_ROLE = 1
|
||||||
|
|||||||
@@ -1,9 +1,9 @@
|
|||||||
from datetime import timedelta
|
from datetime import timedelta
|
||||||
from typing import TYPE_CHECKING
|
|
||||||
|
|
||||||
import pytest
|
import pytest
|
||||||
from django.conf import settings
|
from django.conf import settings
|
||||||
from django.db import ProgrammingError
|
from django.db import ProgrammingError
|
||||||
|
from django.test import Client
|
||||||
from django.urls import reverse
|
from django.urls import reverse
|
||||||
from django.utils.timezone import localdate
|
from django.utils.timezone import localdate
|
||||||
from model_bakery import baker
|
from model_bakery import baker
|
||||||
@@ -14,9 +14,6 @@ from club.models import Club, ClubRole, Membership
|
|||||||
from core.baker_recipes import subscriber_user
|
from core.baker_recipes import subscriber_user
|
||||||
from core.models import User
|
from core.models import User
|
||||||
|
|
||||||
if TYPE_CHECKING:
|
|
||||||
from django.test import Client
|
|
||||||
|
|
||||||
|
|
||||||
@pytest.mark.django_db
|
@pytest.mark.django_db
|
||||||
def test_club_queryset_having_board_member():
|
def test_club_queryset_having_board_member():
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
from typing import TYPE_CHECKING
|
from collections.abc import Callable
|
||||||
|
|
||||||
import pytest
|
import pytest
|
||||||
from django.contrib.auth.models import Permission
|
from django.contrib.auth.models import Permission
|
||||||
@@ -14,9 +14,6 @@ from club.models import Club, ClubRole, Membership
|
|||||||
from core.baker_recipes import subscriber_user
|
from core.baker_recipes import subscriber_user
|
||||||
from core.models import AnonymousUser, User
|
from core.models import AnonymousUser, User
|
||||||
|
|
||||||
if TYPE_CHECKING:
|
|
||||||
from collections.abc import Callable
|
|
||||||
|
|
||||||
|
|
||||||
def make_club():
|
def make_club():
|
||||||
# unittest-style tests cannot use fixture, so we create a function
|
# unittest-style tests cannot use fixture, so we create a function
|
||||||
|
|||||||
@@ -1,6 +1,5 @@
|
|||||||
from typing import TYPE_CHECKING
|
|
||||||
|
|
||||||
import pytest
|
import pytest
|
||||||
|
from django.test import Client
|
||||||
from django.urls import reverse
|
from django.urls import reverse
|
||||||
from model_bakery import baker
|
from model_bakery import baker
|
||||||
from pytest_django.asserts import assertRedirects
|
from pytest_django.asserts import assertRedirects
|
||||||
@@ -8,9 +7,6 @@ from pytest_django.asserts import assertRedirects
|
|||||||
from club.models import Club, ClubRole, Membership
|
from club.models import Club, ClubRole, Membership
|
||||||
from core.baker_recipes import subscriber_user
|
from core.baker_recipes import subscriber_user
|
||||||
|
|
||||||
if TYPE_CHECKING:
|
|
||||||
from django.test import Client
|
|
||||||
|
|
||||||
|
|
||||||
@pytest.mark.django_db
|
@pytest.mark.django_db
|
||||||
def test_club_board_member_cannot_edit_club_properties(client: Client):
|
def test_club_board_member_cannot_edit_club_properties(client: Client):
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
import itertools
|
import itertools
|
||||||
|
from collections.abc import Callable
|
||||||
from datetime import timedelta
|
from datetime import timedelta
|
||||||
from typing import TYPE_CHECKING
|
|
||||||
|
|
||||||
import pytest
|
import pytest
|
||||||
from bs4 import BeautifulSoup
|
from bs4 import BeautifulSoup
|
||||||
@@ -19,9 +19,6 @@ from club.tests.base import TestClub
|
|||||||
from core.baker_recipes import subscriber_user
|
from core.baker_recipes import subscriber_user
|
||||||
from core.models import AnonymousUser, User
|
from core.models import AnonymousUser, User
|
||||||
|
|
||||||
if TYPE_CHECKING:
|
|
||||||
from collections.abc import Callable
|
|
||||||
|
|
||||||
|
|
||||||
class TestMembershipQuerySet(TestClub):
|
class TestMembershipQuerySet(TestClub):
|
||||||
def test_ongoing(self):
|
def test_ongoing(self):
|
||||||
|
|||||||
@@ -1,8 +1,7 @@
|
|||||||
from typing import TYPE_CHECKING
|
|
||||||
|
|
||||||
import pytest
|
import pytest
|
||||||
from aemark import markdown
|
from aemark import markdown
|
||||||
from bs4 import BeautifulSoup
|
from bs4 import BeautifulSoup
|
||||||
|
from django.test import Client
|
||||||
from django.urls import reverse
|
from django.urls import reverse
|
||||||
from model_bakery import baker
|
from model_bakery import baker
|
||||||
from pytest_django.asserts import assertHTMLEqual, assertRedirects
|
from pytest_django.asserts import assertHTMLEqual, assertRedirects
|
||||||
@@ -11,9 +10,6 @@ from club.models import Club, ClubRole, Membership
|
|||||||
from core.baker_recipes import subscriber_user
|
from core.baker_recipes import subscriber_user
|
||||||
from core.models import PageRev, User
|
from core.models import PageRev, User
|
||||||
|
|
||||||
if TYPE_CHECKING:
|
|
||||||
from django.test import Client
|
|
||||||
|
|
||||||
|
|
||||||
@pytest.mark.django_db
|
@pytest.mark.django_db
|
||||||
def test_page_display_on_club_main_page(client: Client):
|
def test_page_display_on_club_main_page(client: Client):
|
||||||
|
|||||||
@@ -1,6 +1,5 @@
|
|||||||
from typing import TYPE_CHECKING
|
|
||||||
|
|
||||||
import pytest
|
import pytest
|
||||||
|
from django.test import Client
|
||||||
from django.urls import reverse
|
from django.urls import reverse
|
||||||
from model_bakery import baker
|
from model_bakery import baker
|
||||||
|
|
||||||
@@ -8,9 +7,6 @@ from club.models import Club
|
|||||||
from com.models import Poster
|
from com.models import Poster
|
||||||
from core.baker_recipes import subscriber_user
|
from core.baker_recipes import subscriber_user
|
||||||
|
|
||||||
if TYPE_CHECKING:
|
|
||||||
from django.test import Client
|
|
||||||
|
|
||||||
|
|
||||||
@pytest.mark.django_db
|
@pytest.mark.django_db
|
||||||
@pytest.mark.parametrize("route_url", ["club:poster_list", "club:poster_create"])
|
@pytest.mark.parametrize("route_url", ["club:poster_list", "club:poster_create"])
|
||||||
|
|||||||
@@ -1,8 +1,8 @@
|
|||||||
import csv
|
import csv
|
||||||
import itertools
|
import itertools
|
||||||
from typing import TYPE_CHECKING
|
|
||||||
|
|
||||||
import pytest
|
import pytest
|
||||||
|
from django.test import Client
|
||||||
from django.urls import reverse
|
from django.urls import reverse
|
||||||
from model_bakery import baker
|
from model_bakery import baker
|
||||||
|
|
||||||
@@ -12,9 +12,6 @@ from core.models import User
|
|||||||
from counter.baker_recipes import product_recipe, sale_recipe
|
from counter.baker_recipes import product_recipe, sale_recipe
|
||||||
from counter.models import Counter, Customer, Product, Selling
|
from counter.models import Counter, Customer, Product, Selling
|
||||||
|
|
||||||
if TYPE_CHECKING:
|
|
||||||
from django.test import Client
|
|
||||||
|
|
||||||
|
|
||||||
@pytest.mark.django_db
|
@pytest.mark.django_db
|
||||||
def test_sales_page_doesnt_crash(client: Client):
|
def test_sales_page_doesnt_crash(client: Client):
|
||||||
|
|||||||
+1
-4
@@ -1,5 +1,4 @@
|
|||||||
from datetime import date
|
from datetime import date
|
||||||
from typing import TYPE_CHECKING
|
|
||||||
|
|
||||||
from dateutil.relativedelta import relativedelta
|
from dateutil.relativedelta import relativedelta
|
||||||
from django import forms
|
from django import forms
|
||||||
@@ -10,13 +9,11 @@ from django.utils.translation import gettext_lazy as _
|
|||||||
from club.models import Club
|
from club.models import Club
|
||||||
from club.widgets.ajax_select import AutoCompleteSelectClub
|
from club.widgets.ajax_select import AutoCompleteSelectClub
|
||||||
from com.models import News, NewsDate, Poster
|
from com.models import News, NewsDate, Poster
|
||||||
|
from core.models import User
|
||||||
from core.utils import get_end_of_semester
|
from core.utils import get_end_of_semester
|
||||||
from core.views.forms import SelectDateTime
|
from core.views.forms import SelectDateTime
|
||||||
from core.views.widgets.markdown import MarkdownInput
|
from core.views.widgets.markdown import MarkdownInput
|
||||||
|
|
||||||
if TYPE_CHECKING:
|
|
||||||
from core.models import User
|
|
||||||
|
|
||||||
|
|
||||||
class PosterForm(forms.ModelForm):
|
class PosterForm(forms.ModelForm):
|
||||||
class Meta:
|
class Meta:
|
||||||
|
|||||||
+2
-7
@@ -1,10 +1,11 @@
|
|||||||
from typing import TYPE_CHECKING
|
from pathlib import Path
|
||||||
|
|
||||||
from dateutil.relativedelta import relativedelta
|
from dateutil.relativedelta import relativedelta
|
||||||
from django.conf import settings
|
from django.conf import settings
|
||||||
from django.contrib.sites.models import Site
|
from django.contrib.sites.models import Site
|
||||||
from django.contrib.syndication.views import add_domain
|
from django.contrib.syndication.views import add_domain
|
||||||
from django.db.models import Count, OuterRef, QuerySet, Subquery
|
from django.db.models import Count, OuterRef, QuerySet, Subquery
|
||||||
|
from django.http import HttpRequest
|
||||||
from django.urls import reverse
|
from django.urls import reverse
|
||||||
from django.utils import timezone
|
from django.utils import timezone
|
||||||
from ical.calendar import Calendar
|
from ical.calendar import Calendar
|
||||||
@@ -13,12 +14,6 @@ from ical.event import Event
|
|||||||
from ical.types import Frequency, Recur
|
from ical.types import Frequency, Recur
|
||||||
|
|
||||||
from com.models import News, NewsDate
|
from com.models import News, NewsDate
|
||||||
|
|
||||||
if TYPE_CHECKING:
|
|
||||||
from pathlib import Path
|
|
||||||
|
|
||||||
from django.http import HttpRequest
|
|
||||||
|
|
||||||
from core.models import User
|
from core.models import User
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -1,11 +1,11 @@
|
|||||||
from datetime import timedelta
|
from datetime import timedelta
|
||||||
from pathlib import Path
|
from pathlib import Path
|
||||||
from typing import TYPE_CHECKING
|
|
||||||
|
|
||||||
import pytest
|
import pytest
|
||||||
from aemark import markdown
|
from aemark import markdown
|
||||||
from django.conf import settings
|
from django.conf import settings
|
||||||
from django.contrib.auth.models import Permission
|
from django.contrib.auth.models import Permission
|
||||||
|
from django.http import HttpResponse
|
||||||
from django.test import Client, TestCase
|
from django.test import Client, TestCase
|
||||||
from django.urls import reverse
|
from django.urls import reverse
|
||||||
from django.utils.timezone import now
|
from django.utils.timezone import now
|
||||||
@@ -16,9 +16,6 @@ from com.ics_calendar import IcsCalendar
|
|||||||
from com.models import News, NewsDate
|
from com.models import News, NewsDate
|
||||||
from core.models import User
|
from core.models import User
|
||||||
|
|
||||||
if TYPE_CHECKING:
|
|
||||||
from django.http import HttpResponse
|
|
||||||
|
|
||||||
|
|
||||||
def accel_redirect_to_file(response: HttpResponse) -> Path | None:
|
def accel_redirect_to_file(response: HttpResponse) -> Path | None:
|
||||||
redirect = Path(response.headers.get("X-Accel-Redirect", ""))
|
redirect = Path(response.headers.get("X-Accel-Redirect", ""))
|
||||||
|
|||||||
@@ -1,12 +1,8 @@
|
|||||||
# Generated by Django 4.2.17 on 2025-01-04 16:42
|
# Generated by Django 4.2.17 on 2025-01-04 16:42
|
||||||
|
|
||||||
from typing import TYPE_CHECKING
|
|
||||||
|
|
||||||
from django.db import migrations
|
from django.db import migrations
|
||||||
from django.db.models import F
|
|
||||||
|
|
||||||
if TYPE_CHECKING:
|
|
||||||
from django.db.migrations.state import StateApps
|
from django.db.migrations.state import StateApps
|
||||||
|
from django.db.models import F
|
||||||
|
|
||||||
|
|
||||||
def invert_is_manually_manageable(apps: StateApps, schema_editor):
|
def invert_is_manually_manageable(apps: StateApps, schema_editor):
|
||||||
|
|||||||
@@ -1,13 +1,9 @@
|
|||||||
# Generated by Django 4.2.17 on 2024-12-31 13:30
|
# Generated by Django 4.2.17 on 2024-12-31 13:30
|
||||||
|
|
||||||
from typing import TYPE_CHECKING
|
|
||||||
|
|
||||||
import django.contrib.auth.models
|
import django.contrib.auth.models
|
||||||
import django.db.models.deletion
|
import django.db.models.deletion
|
||||||
from django.conf import settings
|
from django.conf import settings
|
||||||
from django.db import migrations, models
|
from django.db import migrations, models
|
||||||
|
|
||||||
if TYPE_CHECKING:
|
|
||||||
from django.db.migrations.state import StateApps
|
from django.db.migrations.state import StateApps
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -1,14 +1,10 @@
|
|||||||
# Generated by Django 5.2.12 on 2026-05-01 08:59
|
# Generated by Django 5.2.12 on 2026-05-01 08:59
|
||||||
|
|
||||||
from typing import TYPE_CHECKING
|
|
||||||
|
|
||||||
import django.db.models.deletion
|
import django.db.models.deletion
|
||||||
from django.conf import settings
|
from django.conf import settings
|
||||||
from django.db import migrations, models
|
from django.db import migrations, models
|
||||||
from django.db.models import F
|
|
||||||
|
|
||||||
if TYPE_CHECKING:
|
|
||||||
from django.db.migrations.state import StateApps
|
from django.db.migrations.state import StateApps
|
||||||
|
from django.db.models import F
|
||||||
|
|
||||||
|
|
||||||
def set_updated_at(apps: StateApps, schema_editor):
|
def set_updated_at(apps: StateApps, schema_editor):
|
||||||
|
|||||||
@@ -1,54 +0,0 @@
|
|||||||
{% extends "core/file.jinja" %}
|
|
||||||
|
|
||||||
{% block title %}
|
|
||||||
{% trans %}Delete confirmation{% endtrans %}
|
|
||||||
{% endblock %}
|
|
||||||
|
|
||||||
{% if is_fragment %}
|
|
||||||
|
|
||||||
{# Don't display tabs and errors #}
|
|
||||||
{% block tabs %}
|
|
||||||
{% endblock %}
|
|
||||||
{% block errors %}
|
|
||||||
{% endblock %}
|
|
||||||
|
|
||||||
{% endif %}
|
|
||||||
|
|
||||||
{% block file %}
|
|
||||||
<h2>{% trans %}Delete confirmation{% endtrans %}</h2>
|
|
||||||
|
|
||||||
{% if next %}
|
|
||||||
{% set action = current + "?next=" + next %}
|
|
||||||
{% else %}
|
|
||||||
{% set action = current %}
|
|
||||||
{% endif %}
|
|
||||||
|
|
||||||
<form action="{{ action }}" method="post">
|
|
||||||
{% csrf_token %}
|
|
||||||
|
|
||||||
<p>{% trans obj=object %}Are you sure you want to delete "{{ obj }}"?{% endtrans %}</p>
|
|
||||||
<button
|
|
||||||
{% if is_fragment %}
|
|
||||||
hx-post="{{ action }}"
|
|
||||||
hx-target="#content"
|
|
||||||
hx-swap="outerHtml"
|
|
||||||
{% endif %}
|
|
||||||
>{% trans %}Confirm{% endtrans %}</button>
|
|
||||||
|
|
||||||
<button
|
|
||||||
{% if is_fragment %}
|
|
||||||
hx-get="{{ previous }}"
|
|
||||||
hx-target="#content"
|
|
||||||
hx-swap="outerHtml"
|
|
||||||
{% else %}
|
|
||||||
action="window.history.back()"
|
|
||||||
{% endif %}
|
|
||||||
>{% trans %}Cancel{% endtrans %}</button>
|
|
||||||
|
|
||||||
</form>
|
|
||||||
|
|
||||||
{% endblock %}
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
@@ -20,14 +20,12 @@
|
|||||||
# Place - Suite 330, Boston, MA 02111-1307, USA.
|
# Place - Suite 330, Boston, MA 02111-1307, USA.
|
||||||
#
|
#
|
||||||
#
|
#
|
||||||
from typing import TYPE_CHECKING, Callable
|
from typing import Callable
|
||||||
|
|
||||||
import honeypot.templatetags.honeypot as honeypot_filters
|
import honeypot.templatetags.honeypot as honeypot_filters
|
||||||
from django.template.loader import render_to_string
|
from django.template.loader import render_to_string
|
||||||
from jinja2 import Environment, nodes
|
from jinja2 import Environment, nodes
|
||||||
from jinja2.ext import Extension
|
from jinja2.ext import Extension
|
||||||
|
|
||||||
if TYPE_CHECKING:
|
|
||||||
from jinja2.parser import Parser
|
from jinja2.parser import Parser
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -23,18 +23,15 @@
|
|||||||
#
|
#
|
||||||
|
|
||||||
import datetime
|
import datetime
|
||||||
from typing import TYPE_CHECKING
|
|
||||||
|
|
||||||
import phonenumbers
|
import phonenumbers
|
||||||
from aemark import markdown as md
|
from aemark import markdown as md
|
||||||
from django import template
|
from django import template
|
||||||
|
from django.forms import BoundField
|
||||||
from django.template.defaultfilters import stringfilter
|
from django.template.defaultfilters import stringfilter
|
||||||
from django.utils.safestring import mark_safe
|
from django.utils.safestring import mark_safe
|
||||||
from django.utils.translation import ngettext
|
from django.utils.translation import ngettext
|
||||||
|
|
||||||
if TYPE_CHECKING:
|
|
||||||
from django.forms import BoundField
|
|
||||||
|
|
||||||
register = template.Library()
|
register = template.Library()
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -1,5 +1,4 @@
|
|||||||
from datetime import timedelta
|
from datetime import timedelta
|
||||||
from typing import TYPE_CHECKING
|
|
||||||
|
|
||||||
import freezegun
|
import freezegun
|
||||||
import pytest
|
import pytest
|
||||||
@@ -7,6 +6,7 @@ from aemark import markdown
|
|||||||
from bs4 import BeautifulSoup
|
from bs4 import BeautifulSoup
|
||||||
from django.conf import settings
|
from django.conf import settings
|
||||||
from django.contrib.auth.models import Permission
|
from django.contrib.auth.models import Permission
|
||||||
|
from django.test import Client
|
||||||
from django.urls import reverse
|
from django.urls import reverse
|
||||||
from django.utils.timezone import now
|
from django.utils.timezone import now
|
||||||
from model_bakery import baker
|
from model_bakery import baker
|
||||||
@@ -16,9 +16,6 @@ from club.models import Club, Membership
|
|||||||
from core.baker_recipes import board_user, subscriber_user
|
from core.baker_recipes import board_user, subscriber_user
|
||||||
from core.models import AnonymousUser, Page, PageRev, User
|
from core.models import AnonymousUser, Page, PageRev, User
|
||||||
|
|
||||||
if TYPE_CHECKING:
|
|
||||||
from django.test import Client
|
|
||||||
|
|
||||||
|
|
||||||
@pytest.mark.django_db
|
@pytest.mark.django_db
|
||||||
class TestEditPage:
|
class TestEditPage:
|
||||||
|
|||||||
+6
-22
@@ -21,7 +21,7 @@
|
|||||||
# Place - Suite 330, Boston, MA 02111-1307, USA.
|
# Place - Suite 330, Boston, MA 02111-1307, USA.
|
||||||
#
|
#
|
||||||
#
|
#
|
||||||
from django.urls import path, re_path, register_converter
|
from django.urls import path, register_converter
|
||||||
from django.views.generic import RedirectView
|
from django.views.generic import RedirectView
|
||||||
|
|
||||||
from com.views import NewsListView
|
from com.views import NewsListView
|
||||||
@@ -193,27 +193,11 @@ urlpatterns = [
|
|||||||
name="user_gift_delete",
|
name="user_gift_delete",
|
||||||
),
|
),
|
||||||
# File views
|
# File views
|
||||||
re_path(r"^file/$", FileListView.as_view(), name="file_list"),
|
path(r"file/", FileListView.as_view(), name="file_list"),
|
||||||
re_path(
|
path("file/<int:file_id>/", FileView.as_view(), name="file_detail"),
|
||||||
r"^file/(?P<file_id>[0-9]+)/$",
|
path("file/<int:file_id>/edit/", FileEditView.as_view(), name="file_edit"),
|
||||||
FileView.as_view(),
|
path("file/<int:file_id>/prop/", FileEditPropView.as_view(), name="file_prop"),
|
||||||
name="file_detail",
|
path("file/<int:file_id>/delete/", FileDeleteView.as_view(), name="file_delete"),
|
||||||
),
|
|
||||||
re_path(
|
|
||||||
r"^file/(?P<file_id>[0-9]+)/edit/$",
|
|
||||||
FileEditView.as_view(),
|
|
||||||
name="file_edit",
|
|
||||||
),
|
|
||||||
re_path(
|
|
||||||
r"^file/(?P<file_id>[0-9]+)/prop/$",
|
|
||||||
FileEditPropView.as_view(),
|
|
||||||
name="file_prop",
|
|
||||||
),
|
|
||||||
re_path(
|
|
||||||
r"^file/(?P<file_id>[0-9]+)/delete/$",
|
|
||||||
FileDeleteView.as_view(),
|
|
||||||
name="file_delete",
|
|
||||||
),
|
|
||||||
path("file/moderation/", FileModerationView.as_view(), name="file_moderation"),
|
path("file/moderation/", FileModerationView.as_view(), name="file_moderation"),
|
||||||
path(
|
path(
|
||||||
"file/<int:file_id>/moderate/", FileModerateView.as_view(), name="file_moderate"
|
"file/<int:file_id>/moderate/", FileModerateView.as_view(), name="file_moderate"
|
||||||
|
|||||||
+3
-5
@@ -17,17 +17,15 @@ from datetime import date, timedelta
|
|||||||
|
|
||||||
# Image utils
|
# Image utils
|
||||||
from io import BytesIO
|
from io import BytesIO
|
||||||
from typing import TYPE_CHECKING, Final
|
from typing import Final
|
||||||
|
|
||||||
import PIL
|
import PIL
|
||||||
from django.conf import settings
|
from django.conf import settings
|
||||||
from django.core.files.base import ContentFile
|
from django.core.files.base import ContentFile
|
||||||
from django.utils.timezone import localdate
|
|
||||||
from PIL.Image import Image, Resampling
|
|
||||||
|
|
||||||
if TYPE_CHECKING:
|
|
||||||
from django.core.files.uploadedfile import UploadedFile
|
from django.core.files.uploadedfile import UploadedFile
|
||||||
from django.http import HttpRequest
|
from django.http import HttpRequest
|
||||||
|
from django.utils.timezone import localdate
|
||||||
|
from PIL.Image import Image, Resampling
|
||||||
|
|
||||||
RED_PIXEL_PNG: Final[bytes] = (
|
RED_PIXEL_PNG: Final[bytes] = (
|
||||||
b"\x89\x50\x4e\x47\x0d\x0a\x1a\x0a\x00\x00\x00\x0d\x49\x48\x44\x52"
|
b"\x89\x50\x4e\x47\x0d\x0a\x1a\x0a\x00\x00\x00\x0d\x49\x48\x44\x52"
|
||||||
|
|||||||
+5
-23
@@ -13,7 +13,7 @@
|
|||||||
#
|
#
|
||||||
#
|
#
|
||||||
import mimetypes
|
import mimetypes
|
||||||
from typing import TYPE_CHECKING
|
from pathlib import Path
|
||||||
from urllib.parse import quote, urljoin
|
from urllib.parse import quote, urljoin
|
||||||
|
|
||||||
# This file contains all the views that concern the page model
|
# This file contains all the views that concern the page model
|
||||||
@@ -48,9 +48,6 @@ from core.views.widgets.ajax_select import (
|
|||||||
)
|
)
|
||||||
from counter.utils import is_logged_in_counter
|
from counter.utils import is_logged_in_counter
|
||||||
|
|
||||||
if TYPE_CHECKING:
|
|
||||||
from pathlib import Path
|
|
||||||
|
|
||||||
|
|
||||||
def send_raw_file(path: Path) -> HttpResponse:
|
def send_raw_file(path: Path) -> HttpResponse:
|
||||||
"""Send a file located in the MEDIA_ROOT
|
"""Send a file located in the MEDIA_ROOT
|
||||||
@@ -345,33 +342,18 @@ class FileView(CanViewMixin, DetailView, FormMixin):
|
|||||||
return kwargs
|
return kwargs
|
||||||
|
|
||||||
|
|
||||||
class FileDeleteView(AllowFragment, CanEditPropMixin, DeleteView):
|
class FileDeleteView(CanEditPropMixin, DeleteView):
|
||||||
model = SithFile
|
model = SithFile
|
||||||
pk_url_kwarg = "file_id"
|
pk_url_kwarg = "file_id"
|
||||||
template_name = "core/file_delete_confirm.jinja"
|
template_name = "core/delete_confirm.jinja"
|
||||||
context_object_name = "file"
|
|
||||||
|
|
||||||
def get_success_url(self):
|
def get_success_url(self):
|
||||||
self.object.file.delete() # Doing it here or overloading delete() is the same, so let's do it here
|
self.object.file.delete() # Doing it here or overloading delete() is the same, so let's do it here
|
||||||
if "next" in self.request.GET:
|
if "next" in self.request.GET:
|
||||||
return self.request.GET["next"]
|
return self.request.GET["next"]
|
||||||
if self.object.parent is None:
|
if self.object.parent is None:
|
||||||
return reverse(
|
return reverse("core:file_list")
|
||||||
"core:file_list",
|
return reverse("core:file_detail", kwargs={"file_id": self.object.parent.id})
|
||||||
)
|
|
||||||
return reverse(
|
|
||||||
"core:file_detail",
|
|
||||||
kwargs={
|
|
||||||
"file_id": self.object.parent.id,
|
|
||||||
},
|
|
||||||
)
|
|
||||||
|
|
||||||
def get_context_data(self, **kwargs):
|
|
||||||
kwargs = super().get_context_data(**kwargs)
|
|
||||||
kwargs["next"] = self.request.GET.get("next", None)
|
|
||||||
kwargs["previous"] = self.request.GET.get("previous", None)
|
|
||||||
kwargs["current"] = self.request.path
|
|
||||||
return kwargs
|
|
||||||
|
|
||||||
|
|
||||||
class FileModerationView(AllowFragment, ListView):
|
class FileModerationView(AllowFragment, ListView):
|
||||||
|
|||||||
+1
-4
@@ -22,8 +22,8 @@
|
|||||||
#
|
#
|
||||||
import re
|
import re
|
||||||
from copy import copy
|
from copy import copy
|
||||||
|
from datetime import date, datetime
|
||||||
from io import BytesIO
|
from io import BytesIO
|
||||||
from typing import TYPE_CHECKING
|
|
||||||
|
|
||||||
from captcha.fields import CaptchaField
|
from captcha.fields import CaptchaField
|
||||||
from django import forms
|
from django import forms
|
||||||
@@ -59,9 +59,6 @@ from core.views.widgets.ajax_select import (
|
|||||||
)
|
)
|
||||||
from core.views.widgets.markdown import MarkdownInput
|
from core.views.widgets.markdown import MarkdownInput
|
||||||
|
|
||||||
if TYPE_CHECKING:
|
|
||||||
from datetime import date, datetime
|
|
||||||
|
|
||||||
# Widgets
|
# Widgets
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
+2
-6
@@ -22,11 +22,11 @@
|
|||||||
#
|
#
|
||||||
#
|
#
|
||||||
|
|
||||||
from typing import TYPE_CHECKING
|
|
||||||
|
|
||||||
from django.conf import settings
|
from django.conf import settings
|
||||||
from django.contrib.auth.mixins import LoginRequiredMixin
|
from django.contrib.auth.mixins import LoginRequiredMixin
|
||||||
from django.db.models import F
|
from django.db.models import F
|
||||||
|
from django.db.models.query import QuerySet
|
||||||
|
from django.http import HttpRequest
|
||||||
from django.shortcuts import get_object_or_404, redirect
|
from django.shortcuts import get_object_or_404, redirect
|
||||||
from django.views.generic import ListView, TemplateView
|
from django.views.generic import ListView, TemplateView
|
||||||
|
|
||||||
@@ -34,10 +34,6 @@ from club.models import Club
|
|||||||
from core.models import Notification, User
|
from core.models import Notification, User
|
||||||
from core.schemas import UserFilterSchema
|
from core.schemas import UserFilterSchema
|
||||||
|
|
||||||
if TYPE_CHECKING:
|
|
||||||
from django.db.models.query import QuerySet
|
|
||||||
from django.http import HttpRequest
|
|
||||||
|
|
||||||
|
|
||||||
class NotificationList(LoginRequiredMixin, ListView):
|
class NotificationList(LoginRequiredMixin, ListView):
|
||||||
model = Notification
|
model = Notification
|
||||||
|
|||||||
@@ -1,16 +1,14 @@
|
|||||||
import copy
|
import copy
|
||||||
import inspect
|
import inspect
|
||||||
from typing import TYPE_CHECKING, Any, ClassVar, LiteralString, Protocol, Unpack
|
from typing import Any, ClassVar, LiteralString, Protocol, Unpack
|
||||||
|
|
||||||
from django.core.exceptions import ImproperlyConfigured
|
from django.core.exceptions import ImproperlyConfigured
|
||||||
|
from django.http import HttpRequest, HttpResponse
|
||||||
from django.template.loader import render_to_string
|
from django.template.loader import render_to_string
|
||||||
|
from django.utils.safestring import SafeString
|
||||||
from django.views import View
|
from django.views import View
|
||||||
from django.views.generic.base import ContextMixin, TemplateResponseMixin
|
from django.views.generic.base import ContextMixin, TemplateResponseMixin
|
||||||
|
|
||||||
if TYPE_CHECKING:
|
|
||||||
from django.http import HttpRequest, HttpResponse
|
|
||||||
from django.utils.safestring import SafeString
|
|
||||||
|
|
||||||
|
|
||||||
class TabedViewMixin(View):
|
class TabedViewMixin(View):
|
||||||
"""Basic functions for displaying tabs in the template."""
|
"""Basic functions for displaying tabs in the template."""
|
||||||
|
|||||||
+1
-4
@@ -27,7 +27,6 @@ from datetime import timedelta
|
|||||||
# This file contains all the views that concern the user model
|
# This file contains all the views that concern the user model
|
||||||
from operator import itemgetter
|
from operator import itemgetter
|
||||||
from smtplib import SMTPException
|
from smtplib import SMTPException
|
||||||
from typing import TYPE_CHECKING
|
|
||||||
|
|
||||||
from django.contrib import messages
|
from django.contrib import messages
|
||||||
from django.contrib.auth import login, views
|
from django.contrib.auth import login, views
|
||||||
@@ -44,6 +43,7 @@ from django.shortcuts import get_object_or_404, redirect
|
|||||||
from django.template.loader import render_to_string
|
from django.template.loader import render_to_string
|
||||||
from django.urls import reverse, reverse_lazy
|
from django.urls import reverse, reverse_lazy
|
||||||
from django.utils.decorators import method_decorator
|
from django.utils.decorators import method_decorator
|
||||||
|
from django.utils.safestring import SafeString
|
||||||
from django.utils.translation import gettext as _
|
from django.utils.translation import gettext as _
|
||||||
from django.views.decorators.http import require_POST
|
from django.views.decorators.http import require_POST
|
||||||
from django.views.generic import (
|
from django.views.generic import (
|
||||||
@@ -73,9 +73,6 @@ from counter.models import Refilling, Selling
|
|||||||
from eboutic.models import Invoice
|
from eboutic.models import Invoice
|
||||||
from trombi.views import UserTrombiForm
|
from trombi.views import UserTrombiForm
|
||||||
|
|
||||||
if TYPE_CHECKING:
|
|
||||||
from django.utils.safestring import SafeString
|
|
||||||
|
|
||||||
|
|
||||||
class SithLoginView(views.LoginView):
|
class SithLoginView(views.LoginView):
|
||||||
"""The login View."""
|
"""The login View."""
|
||||||
|
|||||||
@@ -1,18 +1,15 @@
|
|||||||
from typing import TYPE_CHECKING, Any
|
from collections.abc import Collection
|
||||||
|
from typing import Any
|
||||||
|
|
||||||
from django.contrib.staticfiles.storage import staticfiles_storage
|
from django.contrib.staticfiles.storage import staticfiles_storage
|
||||||
|
from django.db.models import Model, QuerySet
|
||||||
from django.forms import Select, SelectMultiple
|
from django.forms import Select, SelectMultiple
|
||||||
|
from ninja import ModelSchema
|
||||||
from pydantic import TypeAdapter
|
from pydantic import TypeAdapter
|
||||||
|
|
||||||
from core.models import Group, SithFile, User
|
from core.models import Group, SithFile, User
|
||||||
from core.schemas import GroupSchema, SithFileSchema, UserProfileSchema
|
from core.schemas import GroupSchema, SithFileSchema, UserProfileSchema
|
||||||
|
|
||||||
if TYPE_CHECKING:
|
|
||||||
from collections.abc import Collection
|
|
||||||
|
|
||||||
from django.db.models import Model, QuerySet
|
|
||||||
from ninja import ModelSchema
|
|
||||||
|
|
||||||
|
|
||||||
class AutoCompleteSelectMixin:
|
class AutoCompleteSelectMixin:
|
||||||
component_name = "autocomplete-select"
|
component_name = "autocomplete-select"
|
||||||
|
|||||||
+2
-4
@@ -3,7 +3,7 @@ import math
|
|||||||
import uuid
|
import uuid
|
||||||
from collections import defaultdict
|
from collections import defaultdict
|
||||||
from datetime import date, datetime, timezone
|
from datetime import date, datetime, timezone
|
||||||
from typing import TYPE_CHECKING, ClassVar
|
from typing import ClassVar
|
||||||
|
|
||||||
from dateutil.relativedelta import relativedelta
|
from dateutil.relativedelta import relativedelta
|
||||||
from django import forms
|
from django import forms
|
||||||
@@ -11,6 +11,7 @@ from django.conf import settings
|
|||||||
from django.core.exceptions import ValidationError
|
from django.core.exceptions import ValidationError
|
||||||
from django.db.models import Exists, OuterRef, Q
|
from django.db.models import Exists, OuterRef, Q
|
||||||
from django.forms import BaseModelFormSet
|
from django.forms import BaseModelFormSet
|
||||||
|
from django.http import HttpRequest
|
||||||
from django.utils.functional import cached_property
|
from django.utils.functional import cached_property
|
||||||
from django.utils.timezone import now
|
from django.utils.timezone import now
|
||||||
from django.utils.translation import gettext_lazy as _
|
from django.utils.translation import gettext_lazy as _
|
||||||
@@ -58,9 +59,6 @@ from counter.widgets.ajax_select import (
|
|||||||
AutoCompleteSelectProduct,
|
AutoCompleteSelectProduct,
|
||||||
)
|
)
|
||||||
|
|
||||||
if TYPE_CHECKING:
|
|
||||||
from django.http import HttpRequest
|
|
||||||
|
|
||||||
|
|
||||||
class BillingInfoForm(forms.ModelForm):
|
class BillingInfoForm(forms.ModelForm):
|
||||||
class Meta:
|
class Meta:
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
|
from collections.abc import Iterable
|
||||||
from operator import attrgetter
|
from operator import attrgetter
|
||||||
from typing import TYPE_CHECKING
|
|
||||||
|
|
||||||
from django.conf import settings
|
from django.conf import settings
|
||||||
from django.core.mail import send_mass_mail
|
from django.core.mail import send_mass_mail
|
||||||
@@ -13,9 +13,6 @@ from django.utils.translation import gettext as _
|
|||||||
from core.models import User, UserQuerySet
|
from core.models import User, UserQuerySet
|
||||||
from counter.models import AccountDump, Counter, Customer, Product, Selling
|
from counter.models import AccountDump, Counter, Customer, Product, Selling
|
||||||
|
|
||||||
if TYPE_CHECKING:
|
|
||||||
from collections.abc import Iterable
|
|
||||||
|
|
||||||
|
|
||||||
class Command(BaseCommand):
|
class Command(BaseCommand):
|
||||||
"""Effectively dump the inactive users.
|
"""Effectively dump the inactive users.
|
||||||
|
|||||||
@@ -1,14 +1,13 @@
|
|||||||
from typing import TYPE_CHECKING, Callable
|
from typing import TYPE_CHECKING, Callable
|
||||||
|
|
||||||
|
from django.http import HttpRequest, HttpResponse
|
||||||
from django.utils.functional import SimpleLazyObject
|
from django.utils.functional import SimpleLazyObject
|
||||||
|
|
||||||
|
from core.models import User
|
||||||
from counter.models import Permanency
|
from counter.models import Permanency
|
||||||
|
|
||||||
if TYPE_CHECKING:
|
if TYPE_CHECKING:
|
||||||
from django.contrib.sessions.backends.base import SessionBase
|
from django.contrib.sessions.backends.base import SessionBase
|
||||||
from django.http import HttpRequest, HttpResponse
|
|
||||||
|
|
||||||
from core.models import User
|
|
||||||
|
|
||||||
|
|
||||||
SESSION_PERMANENCES_KEY = "permanence_ids"
|
SESSION_PERMANENCES_KEY = "permanence_ids"
|
||||||
|
|||||||
@@ -1,13 +1,10 @@
|
|||||||
# Generated by Django 4.2.17 on 2024-12-08 13:30
|
# Generated by Django 4.2.17 on 2024-12-08 13:30
|
||||||
from operator import attrgetter
|
from operator import attrgetter
|
||||||
from typing import TYPE_CHECKING
|
|
||||||
|
|
||||||
import django.db.models.deletion
|
import django.db.models.deletion
|
||||||
from django.db import migrations, models
|
from django.db import migrations, models
|
||||||
from django.db.models import Count
|
|
||||||
|
|
||||||
if TYPE_CHECKING:
|
|
||||||
from django.db.migrations.state import StateApps
|
from django.db.migrations.state import StateApps
|
||||||
|
from django.db.models import Count
|
||||||
|
|
||||||
|
|
||||||
def delete_duplicates(apps: StateApps, schema_editor):
|
def delete_duplicates(apps: StateApps, schema_editor):
|
||||||
|
|||||||
@@ -1,10 +1,6 @@
|
|||||||
# Generated by Django 4.2.17 on 2024-12-15 17:53
|
# Generated by Django 4.2.17 on 2024-12-15 17:53
|
||||||
|
|
||||||
from typing import TYPE_CHECKING
|
|
||||||
|
|
||||||
from django.db import migrations, models
|
from django.db import migrations, models
|
||||||
|
|
||||||
if TYPE_CHECKING:
|
|
||||||
from django.db.migrations.state import StateApps
|
from django.db.migrations.state import StateApps
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -1,12 +1,8 @@
|
|||||||
# Generated by Django 5.2.8 on 2025-11-19 17:59
|
# Generated by Django 5.2.8 on 2025-11-19 17:59
|
||||||
|
|
||||||
from typing import TYPE_CHECKING
|
|
||||||
|
|
||||||
from django.db import migrations, models
|
from django.db import migrations, models
|
||||||
from django.db.models import Case, When
|
|
||||||
|
|
||||||
if TYPE_CHECKING:
|
|
||||||
from django.db.migrations.state import StateApps
|
from django.db.migrations.state import StateApps
|
||||||
|
from django.db.models import Case, When
|
||||||
|
|
||||||
|
|
||||||
def migrate_selling_payment_method(apps: StateApps, schema_editor):
|
def migrate_selling_payment_method(apps: StateApps, schema_editor):
|
||||||
|
|||||||
@@ -1,16 +1,13 @@
|
|||||||
# Generated by Django 5.2.8 on 2026-02-10 15:40
|
# Generated by Django 5.2.8 on 2026-02-10 15:40
|
||||||
from operator import attrgetter
|
from operator import attrgetter
|
||||||
from typing import TYPE_CHECKING
|
|
||||||
|
|
||||||
import django.utils.timezone
|
import django.utils.timezone
|
||||||
from django.db import migrations, models
|
from django.db import migrations, models
|
||||||
|
from django.db.migrations.state import StateApps
|
||||||
from django.db.models import OuterRef, Subquery
|
from django.db.models import OuterRef, Subquery
|
||||||
|
|
||||||
from counter.models import Selling
|
from counter.models import Selling
|
||||||
|
|
||||||
if TYPE_CHECKING:
|
|
||||||
from django.db.migrations.state import StateApps
|
|
||||||
|
|
||||||
|
|
||||||
def apply_product_history_dates(apps: StateApps, schema_editor):
|
def apply_product_history_dates(apps: StateApps, schema_editor):
|
||||||
"""Approximate a posteriori the value of created_at and updated_at."""
|
"""Approximate a posteriori the value of created_at and updated_at."""
|
||||||
|
|||||||
@@ -1,15 +1,11 @@
|
|||||||
# Generated by Django 5.2.11 on 2026-02-18 13:30
|
# Generated by Django 5.2.11 on 2026-02-18 13:30
|
||||||
|
|
||||||
from typing import TYPE_CHECKING
|
|
||||||
|
|
||||||
import django.db.models.deletion
|
import django.db.models.deletion
|
||||||
from django.db import migrations, models
|
from django.db import migrations, models
|
||||||
|
from django.db.migrations.state import StateApps
|
||||||
|
|
||||||
import counter.fields
|
import counter.fields
|
||||||
|
|
||||||
if TYPE_CHECKING:
|
|
||||||
from django.db.migrations.state import StateApps
|
|
||||||
|
|
||||||
|
|
||||||
def migrate_prices(apps: StateApps, schema_editor):
|
def migrate_prices(apps: StateApps, schema_editor):
|
||||||
Product = apps.get_model("counter", "Product")
|
Product = apps.get_model("counter", "Product")
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
|
from collections.abc import Iterable
|
||||||
from datetime import timedelta
|
from datetime import timedelta
|
||||||
from typing import TYPE_CHECKING
|
|
||||||
|
|
||||||
import freezegun
|
import freezegun
|
||||||
import pytest
|
import pytest
|
||||||
@@ -17,9 +17,6 @@ from counter.management.commands.dump_warning_mail import Command as WarningComm
|
|||||||
from counter.models import AccountDump, Customer, Refilling, Selling
|
from counter.models import AccountDump, Customer, Refilling, Selling
|
||||||
from subscription.models import Subscription
|
from subscription.models import Subscription
|
||||||
|
|
||||||
if TYPE_CHECKING:
|
|
||||||
from collections.abc import Iterable
|
|
||||||
|
|
||||||
|
|
||||||
class TestAccountDump(TestCase):
|
class TestAccountDump(TestCase):
|
||||||
@classmethod
|
@classmethod
|
||||||
|
|||||||
@@ -1,9 +1,9 @@
|
|||||||
import json
|
import json
|
||||||
from datetime import timedelta
|
from datetime import timedelta
|
||||||
from typing import TYPE_CHECKING
|
|
||||||
|
|
||||||
import pytest
|
import pytest
|
||||||
from django.conf import settings
|
from django.conf import settings
|
||||||
|
from django.test import Client
|
||||||
from django.urls import reverse
|
from django.urls import reverse
|
||||||
from django.utils.timezone import now
|
from django.utils.timezone import now
|
||||||
from django_celery_beat.models import ClockedSchedule
|
from django_celery_beat.models import ClockedSchedule
|
||||||
@@ -18,9 +18,6 @@ from counter.forms import (
|
|||||||
)
|
)
|
||||||
from counter.models import Product, ProductType, ScheduledProductAction
|
from counter.models import Product, ProductType, ScheduledProductAction
|
||||||
|
|
||||||
if TYPE_CHECKING:
|
|
||||||
from django.test import Client
|
|
||||||
|
|
||||||
|
|
||||||
@pytest.mark.django_db
|
@pytest.mark.django_db
|
||||||
def test_edit_product(client: Client):
|
def test_edit_product(client: Client):
|
||||||
|
|||||||
@@ -15,7 +15,6 @@
|
|||||||
from dataclasses import asdict, dataclass
|
from dataclasses import asdict, dataclass
|
||||||
from datetime import timedelta
|
from datetime import timedelta
|
||||||
from decimal import Decimal
|
from decimal import Decimal
|
||||||
from typing import TYPE_CHECKING
|
|
||||||
|
|
||||||
import pytest
|
import pytest
|
||||||
from bs4 import BeautifulSoup
|
from bs4 import BeautifulSoup
|
||||||
@@ -23,6 +22,7 @@ from dateutil.relativedelta import relativedelta
|
|||||||
from django.conf import settings
|
from django.conf import settings
|
||||||
from django.contrib.auth.models import Permission, make_password
|
from django.contrib.auth.models import Permission, make_password
|
||||||
from django.contrib.messages import DEFAULT_LEVELS, get_messages
|
from django.contrib.messages import DEFAULT_LEVELS, get_messages
|
||||||
|
from django.http import HttpResponse
|
||||||
from django.shortcuts import resolve_url
|
from django.shortcuts import resolve_url
|
||||||
from django.test import Client, TestCase
|
from django.test import Client, TestCase
|
||||||
from django.urls import reverse
|
from django.urls import reverse
|
||||||
@@ -48,9 +48,6 @@ from counter.models import (
|
|||||||
Selling,
|
Selling,
|
||||||
)
|
)
|
||||||
|
|
||||||
if TYPE_CHECKING:
|
|
||||||
from django.http import HttpResponse
|
|
||||||
|
|
||||||
|
|
||||||
def set_age(user: User, age: int):
|
def set_age(user: User, age: int):
|
||||||
user.date_of_birth = localdate().replace(year=localdate().year - age)
|
user.date_of_birth = localdate().replace(year=localdate().year - age)
|
||||||
|
|||||||
@@ -1,10 +1,10 @@
|
|||||||
from datetime import date, datetime
|
from datetime import date, datetime
|
||||||
from typing import TYPE_CHECKING
|
|
||||||
|
|
||||||
import pytest
|
import pytest
|
||||||
from dateutil.relativedelta import relativedelta
|
from dateutil.relativedelta import relativedelta
|
||||||
from django.contrib.auth.models import Permission
|
from django.contrib.auth.models import Permission
|
||||||
from django.core.exceptions import ValidationError
|
from django.core.exceptions import ValidationError
|
||||||
|
from django.test import Client
|
||||||
from django.urls import reverse
|
from django.urls import reverse
|
||||||
from django.utils.timezone import now
|
from django.utils.timezone import now
|
||||||
from model_bakery import baker
|
from model_bakery import baker
|
||||||
@@ -16,9 +16,6 @@ from counter.baker_recipes import sale_recipe
|
|||||||
from counter.forms import InvoiceCallForm
|
from counter.forms import InvoiceCallForm
|
||||||
from counter.models import Customer, InvoiceCall, Selling
|
from counter.models import Customer, InvoiceCall, Selling
|
||||||
|
|
||||||
if TYPE_CHECKING:
|
|
||||||
from django.test import Client
|
|
||||||
|
|
||||||
|
|
||||||
@pytest.mark.django_db
|
@pytest.mark.django_db
|
||||||
@pytest.mark.parametrize(
|
@pytest.mark.parametrize(
|
||||||
|
|||||||
@@ -1,7 +1,6 @@
|
|||||||
from typing import TYPE_CHECKING
|
|
||||||
|
|
||||||
import pytest
|
import pytest
|
||||||
from django.conf import settings
|
from django.conf import settings
|
||||||
|
from django.test import Client
|
||||||
from django.urls import reverse
|
from django.urls import reverse
|
||||||
from model_bakery import baker, seq
|
from model_bakery import baker, seq
|
||||||
|
|
||||||
@@ -9,9 +8,6 @@ from core.baker_recipes import board_user, subscriber_user
|
|||||||
from core.models import Group, User
|
from core.models import Group, User
|
||||||
from counter.models import ProductType
|
from counter.models import ProductType
|
||||||
|
|
||||||
if TYPE_CHECKING:
|
|
||||||
from django.test import Client
|
|
||||||
|
|
||||||
|
|
||||||
@pytest.fixture
|
@pytest.fixture
|
||||||
def product_types(db) -> list[ProductType]:
|
def product_types(db) -> list[ProductType]:
|
||||||
|
|||||||
+1
-4
@@ -1,10 +1,7 @@
|
|||||||
from typing import TYPE_CHECKING
|
|
||||||
from urllib.parse import urlparse
|
from urllib.parse import urlparse
|
||||||
|
|
||||||
from django.urls import resolve
|
|
||||||
|
|
||||||
if TYPE_CHECKING:
|
|
||||||
from django.http import HttpRequest
|
from django.http import HttpRequest
|
||||||
|
from django.urls import resolve
|
||||||
|
|
||||||
|
|
||||||
def is_logged_in_counter(request: HttpRequest) -> bool:
|
def is_logged_in_counter(request: HttpRequest) -> bool:
|
||||||
|
|||||||
@@ -13,8 +13,6 @@
|
|||||||
#
|
#
|
||||||
#
|
#
|
||||||
|
|
||||||
from typing import TYPE_CHECKING
|
|
||||||
|
|
||||||
from django import forms
|
from django import forms
|
||||||
from django.conf import settings
|
from django.conf import settings
|
||||||
from django.contrib.auth.mixins import PermissionRequiredMixin
|
from django.contrib.auth.mixins import PermissionRequiredMixin
|
||||||
@@ -24,6 +22,7 @@ from django.utils.translation import gettext_lazy as _
|
|||||||
from django.views.generic import DetailView, ListView
|
from django.views.generic import DetailView, ListView
|
||||||
from django.views.generic.edit import BaseFormView, UpdateView
|
from django.views.generic.edit import BaseFormView, UpdateView
|
||||||
|
|
||||||
|
from core.models import User
|
||||||
from counter.forms import CashSummaryFormBase
|
from counter.forms import CashSummaryFormBase
|
||||||
from counter.models import (
|
from counter.models import (
|
||||||
CashRegisterSummary,
|
CashRegisterSummary,
|
||||||
@@ -36,9 +35,6 @@ from counter.views.mixins import (
|
|||||||
CounterTabsMixin,
|
CounterTabsMixin,
|
||||||
)
|
)
|
||||||
|
|
||||||
if TYPE_CHECKING:
|
|
||||||
from core.models import User
|
|
||||||
|
|
||||||
|
|
||||||
class CashRegisterSummaryForm(forms.Form):
|
class CashRegisterSummaryForm(forms.Form):
|
||||||
"""Provide the cash summary form."""
|
"""Provide the cash summary form."""
|
||||||
|
|||||||
@@ -14,7 +14,6 @@
|
|||||||
#
|
#
|
||||||
import random
|
import random
|
||||||
from collections import defaultdict
|
from collections import defaultdict
|
||||||
from typing import TYPE_CHECKING
|
|
||||||
|
|
||||||
from django.contrib import messages
|
from django.contrib import messages
|
||||||
from django.core.exceptions import PermissionDenied
|
from django.core.exceptions import PermissionDenied
|
||||||
@@ -23,11 +22,14 @@ from django.db.models import Q
|
|||||||
from django.http import Http404
|
from django.http import Http404
|
||||||
from django.shortcuts import get_object_or_404, redirect, resolve_url
|
from django.shortcuts import get_object_or_404, redirect, resolve_url
|
||||||
from django.urls import reverse
|
from django.urls import reverse
|
||||||
|
from django.utils.safestring import SafeString
|
||||||
from django.utils.translation import gettext as _
|
from django.utils.translation import gettext as _
|
||||||
from django.views.generic import CreateView, FormView
|
from django.views.generic import CreateView, FormView
|
||||||
from django.views.generic.detail import SingleObjectMixin
|
from django.views.generic.detail import SingleObjectMixin
|
||||||
|
from ninja.main import HttpRequest
|
||||||
|
|
||||||
from core.auth.mixins import CanViewMixin
|
from core.auth.mixins import CanViewMixin
|
||||||
|
from core.models import User
|
||||||
from core.views.mixins import FragmentMixin, UseFragmentsMixin
|
from core.views.mixins import FragmentMixin, UseFragmentsMixin
|
||||||
from counter.forms import BasketForm, RefillForm
|
from counter.forms import BasketForm, RefillForm
|
||||||
from counter.models import (
|
from counter.models import (
|
||||||
@@ -42,12 +44,6 @@ from counter.utils import is_logged_in_counter
|
|||||||
from counter.views.mixins import CounterTabsMixin
|
from counter.views.mixins import CounterTabsMixin
|
||||||
from counter.views.student_card import StudentCardFormFragment
|
from counter.views.student_card import StudentCardFormFragment
|
||||||
|
|
||||||
if TYPE_CHECKING:
|
|
||||||
from django.utils.safestring import SafeString
|
|
||||||
from ninja.main import HttpRequest
|
|
||||||
|
|
||||||
from core.models import User
|
|
||||||
|
|
||||||
|
|
||||||
def get_operator(request: HttpRequest, counter: Counter, customer: Customer) -> User:
|
def get_operator(request: HttpRequest, counter: Counter, customer: Customer) -> User:
|
||||||
if counter.type != "BAR":
|
if counter.type != "BAR":
|
||||||
|
|||||||
@@ -13,7 +13,6 @@
|
|||||||
#
|
#
|
||||||
#
|
#
|
||||||
from datetime import timedelta
|
from datetime import timedelta
|
||||||
from typing import TYPE_CHECKING
|
|
||||||
|
|
||||||
from django.conf import settings
|
from django.conf import settings
|
||||||
from django.core.exceptions import PermissionDenied
|
from django.core.exceptions import PermissionDenied
|
||||||
@@ -22,6 +21,7 @@ from django.http import HttpRequest, HttpResponseRedirect
|
|||||||
from django.shortcuts import redirect
|
from django.shortcuts import redirect
|
||||||
from django.urls import reverse
|
from django.urls import reverse
|
||||||
from django.utils import timezone
|
from django.utils import timezone
|
||||||
|
from django.utils.safestring import SafeString
|
||||||
from django.views.decorators.http import require_POST
|
from django.views.decorators.http import require_POST
|
||||||
from django.views.generic import DetailView
|
from django.views.generic import DetailView
|
||||||
from django.views.generic.detail import SingleObjectMixin
|
from django.views.generic.detail import SingleObjectMixin
|
||||||
@@ -35,9 +35,6 @@ from counter.models import Counter, Permanency
|
|||||||
from counter.utils import is_logged_in_counter
|
from counter.utils import is_logged_in_counter
|
||||||
from counter.views.mixins import CounterTabsMixin
|
from counter.views.mixins import CounterTabsMixin
|
||||||
|
|
||||||
if TYPE_CHECKING:
|
|
||||||
from django.utils.safestring import SafeString
|
|
||||||
|
|
||||||
|
|
||||||
class CounterLoginFragment(FragmentMixin, SingleObjectMixin, FormView):
|
class CounterLoginFragment(FragmentMixin, SingleObjectMixin, FormView):
|
||||||
model = Counter
|
model = Counter
|
||||||
|
|||||||
@@ -13,12 +13,11 @@
|
|||||||
#
|
#
|
||||||
#
|
#
|
||||||
|
|
||||||
from typing import TYPE_CHECKING
|
|
||||||
|
|
||||||
from django.core.exceptions import PermissionDenied
|
from django.core.exceptions import PermissionDenied
|
||||||
from django.http import Http404, HttpRequest, HttpResponse
|
from django.http import Http404, HttpRequest, HttpResponse
|
||||||
from django.shortcuts import get_object_or_404
|
from django.shortcuts import get_object_or_404
|
||||||
from django.urls import reverse
|
from django.urls import reverse
|
||||||
|
from django.utils.safestring import SafeString
|
||||||
from django.utils.translation import gettext as _
|
from django.utils.translation import gettext as _
|
||||||
from django.views.generic.edit import DeleteView, FormView
|
from django.views.generic.edit import DeleteView, FormView
|
||||||
|
|
||||||
@@ -28,9 +27,6 @@ from counter.forms import StudentCardForm
|
|||||||
from counter.models import Customer, StudentCard
|
from counter.models import Customer, StudentCard
|
||||||
from counter.utils import is_logged_in_counter
|
from counter.utils import is_logged_in_counter
|
||||||
|
|
||||||
if TYPE_CHECKING:
|
|
||||||
from django.utils.safestring import SafeString
|
|
||||||
|
|
||||||
|
|
||||||
class StudentCardDeleteView(DeleteView):
|
class StudentCardDeleteView(DeleteView):
|
||||||
"""View used to delete a card from a user. This is a fragment view !"""
|
"""View used to delete a card from a user. This is a fragment view !"""
|
||||||
|
|||||||
@@ -1,12 +1,13 @@
|
|||||||
import re
|
import re
|
||||||
from datetime import datetime, timezone
|
from datetime import datetime, timezone
|
||||||
from typing import TYPE_CHECKING
|
|
||||||
|
|
||||||
import freezegun
|
import freezegun
|
||||||
import pytest
|
import pytest
|
||||||
from bs4 import BeautifulSoup
|
from bs4 import BeautifulSoup
|
||||||
from django.conf import settings
|
from django.conf import settings
|
||||||
|
from django.http import HttpResponse
|
||||||
from django.test import TestCase
|
from django.test import TestCase
|
||||||
|
from django.test.client import Client
|
||||||
from django.urls import reverse
|
from django.urls import reverse
|
||||||
from django.utils.timezone import localdate, now
|
from django.utils.timezone import localdate, now
|
||||||
from model_bakery import baker
|
from model_bakery import baker
|
||||||
@@ -30,10 +31,6 @@ from counter.models import (
|
|||||||
from counter.tests.test_counter import BasketItem
|
from counter.tests.test_counter import BasketItem
|
||||||
from eboutic.models import Basket
|
from eboutic.models import Basket
|
||||||
|
|
||||||
if TYPE_CHECKING:
|
|
||||||
from django.http import HttpResponse
|
|
||||||
from django.test.client import Client
|
|
||||||
|
|
||||||
|
|
||||||
@pytest.mark.django_db
|
@pytest.mark.django_db
|
||||||
def test_get_eboutic():
|
def test_get_eboutic():
|
||||||
|
|||||||
@@ -1,6 +1,7 @@
|
|||||||
from typing import TYPE_CHECKING, Callable
|
from typing import Callable
|
||||||
|
|
||||||
import pytest
|
import pytest
|
||||||
|
from django.test import Client
|
||||||
from django.urls import reverse
|
from django.urls import reverse
|
||||||
from model_bakery import baker
|
from model_bakery import baker
|
||||||
from pytest_django.asserts import assertRedirects
|
from pytest_django.asserts import assertRedirects
|
||||||
@@ -9,9 +10,6 @@ from core.baker_recipes import subscriber_user
|
|||||||
from core.models import User
|
from core.models import User
|
||||||
from counter.models import BillingInfo
|
from counter.models import BillingInfo
|
||||||
|
|
||||||
if TYPE_CHECKING:
|
|
||||||
from django.test import Client
|
|
||||||
|
|
||||||
|
|
||||||
@pytest.mark.django_db
|
@pytest.mark.django_db
|
||||||
class TestBillingInfo:
|
class TestBillingInfo:
|
||||||
|
|||||||
+1
-4
@@ -1,7 +1,6 @@
|
|||||||
from datetime import timedelta
|
from datetime import timedelta
|
||||||
from itertools import groupby, islice
|
from itertools import groupby, islice
|
||||||
from operator import attrgetter
|
from operator import attrgetter
|
||||||
from typing import TYPE_CHECKING
|
|
||||||
|
|
||||||
from django import forms
|
from django import forms
|
||||||
from django.conf import settings
|
from django.conf import settings
|
||||||
@@ -14,6 +13,7 @@ from django.utils.translation import gettext_lazy as _
|
|||||||
from club.forms import ClubRoleChoiceField
|
from club.forms import ClubRoleChoiceField
|
||||||
from club.models import ClubRole, Membership
|
from club.models import ClubRole, Membership
|
||||||
from club.widgets.ajax_select import AutoCompleteSelectMultipleClub
|
from club.widgets.ajax_select import AutoCompleteSelectMultipleClub
|
||||||
|
from core.models import User
|
||||||
from core.views.forms import SelectDateTime
|
from core.views.forms import SelectDateTime
|
||||||
from core.views.widgets.ajax_select import (
|
from core.views.widgets.ajax_select import (
|
||||||
AutoCompleteSelect,
|
AutoCompleteSelect,
|
||||||
@@ -23,9 +23,6 @@ from core.views.widgets.ajax_select import (
|
|||||||
from core.views.widgets.markdown import MarkdownInput
|
from core.views.widgets.markdown import MarkdownInput
|
||||||
from election.models import Candidature, Election, ElectionList, Role
|
from election.models import Candidature, Election, ElectionList, Role
|
||||||
|
|
||||||
if TYPE_CHECKING:
|
|
||||||
from core.models import User
|
|
||||||
|
|
||||||
|
|
||||||
class LimitedCheckboxField(forms.ModelMultipleChoiceField):
|
class LimitedCheckboxField(forms.ModelMultipleChoiceField):
|
||||||
"""A `ModelMultipleChoiceField`, with a max limit of selectable inputs."""
|
"""A `ModelMultipleChoiceField`, with a max limit of selectable inputs."""
|
||||||
|
|||||||
+1
-5
@@ -13,19 +13,15 @@
|
|||||||
#
|
#
|
||||||
#
|
#
|
||||||
|
|
||||||
from typing import TYPE_CHECKING
|
|
||||||
|
|
||||||
import pytest
|
import pytest
|
||||||
from django.conf import settings
|
from django.conf import settings
|
||||||
|
from django.test import Client
|
||||||
from django.urls import reverse
|
from django.urls import reverse
|
||||||
from pytest_django.asserts import assertRedirects
|
from pytest_django.asserts import assertRedirects
|
||||||
|
|
||||||
from core.models import User
|
from core.models import User
|
||||||
from forum.models import Forum, ForumMessage, ForumTopic
|
from forum.models import Forum, ForumMessage, ForumTopic
|
||||||
|
|
||||||
if TYPE_CHECKING:
|
|
||||||
from django.test import Client
|
|
||||||
|
|
||||||
|
|
||||||
@pytest.mark.django_db
|
@pytest.mark.django_db
|
||||||
class TestTopicCreation:
|
class TestTopicCreation:
|
||||||
|
|||||||
@@ -91,6 +91,7 @@ class UE(models.Model):
|
|||||||
|
|
||||||
# All texts about the UE
|
# All texts about the UE
|
||||||
title = models.CharField(_("title"), max_length=300)
|
title = models.CharField(_("title"), max_length=300)
|
||||||
|
manager = models.CharField(_("ue manager"), max_length=300)
|
||||||
objectives = models.TextField(_("objectives"))
|
objectives = models.TextField(_("objectives"))
|
||||||
program = models.TextField(_("program"))
|
program = models.TextField(_("program"))
|
||||||
skills = models.TextField(_("skills"))
|
skills = models.TextField(_("skills"))
|
||||||
|
|||||||
+49
-35
@@ -1,5 +1,9 @@
|
|||||||
import { getCurrentUrlParams, updateQueryString } from "#core:utils/history";
|
import {
|
||||||
import { type SimpleUeSchema, ueFetchUeList } from "#openapi";
|
getCurrentUrlParams,
|
||||||
|
History,
|
||||||
|
updateQueryString,
|
||||||
|
} from "#core:utils/history.ts";
|
||||||
|
import { ueFetchUeList } from "#openapi";
|
||||||
|
|
||||||
const pageDefault = 1;
|
const pageDefault = 1;
|
||||||
const pageSizeDefault = 100;
|
const pageSizeDefault = 100;
|
||||||
@@ -8,42 +12,38 @@ document.addEventListener("alpine:init", () => {
|
|||||||
Alpine.data("ue_search", () => ({
|
Alpine.data("ue_search", () => ({
|
||||||
ues: {
|
ues: {
|
||||||
count: 0,
|
count: 0,
|
||||||
next: null as string | null,
|
next: null,
|
||||||
previous: null as string | null,
|
previous: null,
|
||||||
results: [] as SimpleUeSchema[],
|
results: [],
|
||||||
},
|
},
|
||||||
loading: false,
|
loading: false,
|
||||||
page: pageDefault,
|
page: pageDefault,
|
||||||
// biome-ignore lint/style/useNamingConvention: api is in snake_case
|
// biome-ignore lint/style/useNamingConvention: api is in snake_case
|
||||||
page_size: pageSizeDefault,
|
page_size: pageSizeDefault,
|
||||||
search: "",
|
search: "",
|
||||||
department: [] as string[],
|
department: [],
|
||||||
// biome-ignore lint/style/useNamingConvention: api is in snake_case
|
// biome-ignore lint/style/useNamingConvention: api is in snake_case
|
||||||
credit_type: [] as string[],
|
credit_type: [],
|
||||||
semester: [] as string[],
|
semester: [],
|
||||||
// biome-ignore lint/style/useNamingConvention: api is in snake_case
|
// biome-ignore lint/style/useNamingConvention: api is in snake_case
|
||||||
to_change: [] as { param: string; value: string }[],
|
to_change: [],
|
||||||
|
pushstate: History.Push,
|
||||||
|
|
||||||
// dummy implementation to make TS happy.
|
update: undefined,
|
||||||
// The real function is initialized in init
|
|
||||||
update: () => {
|
|
||||||
console.warn("Update not yet initialized");
|
|
||||||
},
|
|
||||||
|
|
||||||
initializeArgs() {
|
initializeArgs() {
|
||||||
const url = getCurrentUrlParams();
|
const url = getCurrentUrlParams();
|
||||||
this.page = Number.parseInt(url.get("page") || pageDefault.toString(), 10);
|
this.pushstate = History.Replace;
|
||||||
this.page_size = Number.parseInt(
|
|
||||||
url.get("page_size") || pageSizeDefault.toString(),
|
this.page = Number.parseInt(url.get("page"), 10) || pageDefault;
|
||||||
10,
|
this.page_size = Number.parseInt(url.get("page_size"), 10) || pageSizeDefault;
|
||||||
);
|
|
||||||
this.search = url.get("search") || "";
|
this.search = url.get("search") || "";
|
||||||
this.department = url.getAll("department");
|
this.department = url.getAll("department");
|
||||||
this.credit_type = url.getAll("credit_type");
|
this.credit_type = url.getAll("credit_type");
|
||||||
/* The semester is easier to use on the backend as an enum (spring/autumn/both/none)
|
/* The semester is easier to use on the backend as an enum (spring/autumn/both/none)
|
||||||
and easier to use on the frontend as an array ([spring, autumn]).
|
and easier to use on the frontend as an array ([spring, autumn]).
|
||||||
Thus there is some conversion involved when both communicate together */
|
Thus there is some conversion involved when both communicate together */
|
||||||
this.semester = url.get("semester")?.split("_AND_") || [];
|
this.semester = url.has("semester") ? url.get("semester").split("_AND_") : [];
|
||||||
|
|
||||||
this.update();
|
this.update();
|
||||||
},
|
},
|
||||||
@@ -51,11 +51,15 @@ document.addEventListener("alpine:init", () => {
|
|||||||
async init() {
|
async init() {
|
||||||
this.update = Alpine.debounce(async () => {
|
this.update = Alpine.debounce(async () => {
|
||||||
/* Create the whole url before changing everything all at once */
|
/* Create the whole url before changing everything all at once */
|
||||||
for (const val of this.to_change) {
|
const first = this.to_change.shift();
|
||||||
updateQueryString(val.param, val.value);
|
let url = updateQueryString(first.param, first.value, History.None);
|
||||||
|
for (const value of this.to_change) {
|
||||||
|
url = updateQueryString(value.param, value.value, History.None, url);
|
||||||
}
|
}
|
||||||
|
updateQueryString(first.param, first.value, this.pushstate, url);
|
||||||
await this.fetchData(); /* reload data on form change */
|
await this.fetchData(); /* reload data on form change */
|
||||||
this.to_change = [];
|
this.to_change = [];
|
||||||
|
this.pushstate = History.Push;
|
||||||
}, 50);
|
}, 50);
|
||||||
|
|
||||||
const searchParams = ["search", "department", "credit_type", "semester"];
|
const searchParams = ["search", "department", "credit_type", "semester"];
|
||||||
@@ -63,37 +67,47 @@ document.addEventListener("alpine:init", () => {
|
|||||||
|
|
||||||
for (const param of searchParams) {
|
for (const param of searchParams) {
|
||||||
this.$watch(param, () => {
|
this.$watch(param, () => {
|
||||||
|
if (this.pushstate !== History.Push) {
|
||||||
|
/* This means that we are doing a mass param edit */
|
||||||
|
return;
|
||||||
|
}
|
||||||
/* Reset pagination on search */
|
/* Reset pagination on search */
|
||||||
this.page = pageDefault;
|
this.page = pageDefault;
|
||||||
this.page_size = pageSizeDefault;
|
this.page_size = pageSizeDefault;
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
for (const param of searchParams.concat(paginationParams)) {
|
for (const param of searchParams.concat(paginationParams)) {
|
||||||
this.$watch(param, (value: string) => {
|
this.$watch(param, (value) => {
|
||||||
this.to_change.push({ param: param, value: value });
|
this.to_change.push({ param: param, value: value });
|
||||||
this.update();
|
this.update();
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
window.addEventListener("popstate", () => {
|
||||||
|
this.initializeArgs();
|
||||||
|
});
|
||||||
this.initializeArgs();
|
this.initializeArgs();
|
||||||
},
|
},
|
||||||
|
|
||||||
async fetchData() {
|
async fetchData() {
|
||||||
this.loading = true;
|
this.loading = true;
|
||||||
|
const args = {
|
||||||
const res = await ueFetchUeList({
|
|
||||||
query: {
|
|
||||||
// biome-ignore lint/style/useNamingConvention: api is in snake_case
|
// biome-ignore lint/style/useNamingConvention: api is in snake_case
|
||||||
page_size: this.page_size,
|
page_size: this.page_size,
|
||||||
// biome-ignore lint/style/useNamingConvention: api is in snake_case
|
};
|
||||||
credit_type: this.credit_type.length > 0 ? this.credit_type : undefined,
|
for (const [param, value] of new URL(
|
||||||
semester: this.semester.length > 0 ? this.semester : undefined,
|
window.location.href,
|
||||||
department: this.department.length > 0 ? this.department : undefined,
|
).searchParams.entries()) {
|
||||||
search: this.search || undefined,
|
// Deal with array type params
|
||||||
},
|
if (["credit_type", "department", "semester"].includes(param)) {
|
||||||
});
|
if (args[param] === undefined) {
|
||||||
if (res.data !== undefined) {
|
args[param] = [];
|
||||||
this.ues = res.data;
|
|
||||||
}
|
}
|
||||||
|
args[param].push(value);
|
||||||
|
} else {
|
||||||
|
args[param] = value;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
this.ues = (await ueFetchUeList({ query: args })).data;
|
||||||
this.loading = false;
|
this.loading = false;
|
||||||
},
|
},
|
||||||
|
|
||||||
+14
-21
@@ -17,25 +17,25 @@ authors = [
|
|||||||
{ name = "Vial", email = "robin.trioux@utbm.fr" },
|
{ name = "Vial", email = "robin.trioux@utbm.fr" },
|
||||||
]
|
]
|
||||||
license = { text = "GPL-3.0-only" }
|
license = { text = "GPL-3.0-only" }
|
||||||
requires-python = "<4.0,>=3.14"
|
requires-python = "<4.0,>=3.12"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"django>=5.2.17,<6.0.0",
|
"django>=5.2.17,<6.0.0",
|
||||||
"django-ninja>=1.7.0,<2.0.0",
|
"django-ninja>=1.6.3,<2.0.0",
|
||||||
"django-ninja-extra>=0.31.7",
|
"django-ninja-extra>=0.31.7",
|
||||||
"Pillow>=12.3.0,<13.0.0",
|
"Pillow>=12.3.0,<13.0.0",
|
||||||
"aemark>=0.1.1",
|
"aemark>=0.1.1",
|
||||||
"django-jinja<3.0.0,>=2.11.0",
|
"django-jinja<3.0.0,>=2.11.0",
|
||||||
"cryptography>=50.0.1,<51.0.0",
|
"cryptography>=50.0.0,<51.0.0",
|
||||||
"django-phonenumber-field>=8.5.0,<9.0.0",
|
"django-phonenumber-field>=8.5.0,<9.0.0",
|
||||||
"phonenumbers>=9.0.38,<10.0.0",
|
"phonenumbers>=9.0.37,<10.0.0",
|
||||||
"reportlab>=5.0.1,<6.0.0",
|
"reportlab>=5.0.1,<6.0.0",
|
||||||
"django-haystack>=3.4.0,<4.0.0",
|
"django-haystack>=3.4.0,<4.0.0",
|
||||||
"xapian-haystack>=4.0.0,<5.0.0",
|
"xapian-haystack>=4.0.0,<5.0.0",
|
||||||
"libsass>=0.23.0,<1.0.0",
|
"libsass>=0.23.0,<1.0.0",
|
||||||
"django-ordered-model>=3.7.4,<4.0.0",
|
"django-ordered-model>=3.7.4,<4.0.0",
|
||||||
"django-simple-captcha>=0.7.0,<1.0.0",
|
"django-simple-captcha>=0.7.0,<1.0.0",
|
||||||
"python-dateutil>=2.9.0.post0,<3.0.0",
|
"python-dateutil>=2.9.0.post0,<3.0.0.0",
|
||||||
"sentry-sdk>=2.68.1,<3.0.0",
|
"sentry-sdk>=2.68.0,<3.0.0",
|
||||||
"jinja2>=3.1.6,<4.0.0",
|
"jinja2>=3.1.6,<4.0.0",
|
||||||
"django-countries>=9.0.0,<10.0.0",
|
"django-countries>=9.0.0,<10.0.0",
|
||||||
"dict2xml>=1.7.8,<2.0.0",
|
"dict2xml>=1.7.8,<2.0.0",
|
||||||
@@ -43,13 +43,13 @@ dependencies = [
|
|||||||
"tomli>=2.4.1,<3.0.0",
|
"tomli>=2.4.1,<3.0.0",
|
||||||
"django-honeypot>=1.3.0,<2",
|
"django-honeypot>=1.3.0,<2",
|
||||||
"pydantic-extra-types>=2.11.1,<3.0.0",
|
"pydantic-extra-types>=2.11.1,<3.0.0",
|
||||||
"ical>=14.1.1",
|
"ical>=12.0.0",
|
||||||
"redis[hiredis]>=6.4.0,<9.0.0",
|
"redis[hiredis]>=6.4.0,<9.0.0",
|
||||||
"environs[django]>=15.1.0,<16",
|
"environs[django]>=15.1.0,<16",
|
||||||
"requests>=2.34.2,<3.0.0",
|
"requests>=2.34.2,<3.0.0",
|
||||||
"honcho>=2.0.0",
|
"honcho>=2.0.0",
|
||||||
"psutil>=7.2.2,<8.0.0",
|
"psutil>=7.2.2,<8.0.0",
|
||||||
"celery[redis]>=5.6.2,<7",
|
"celery[redis]>=5.6.3,<8",
|
||||||
"django-celery-results>=2.6.0",
|
"django-celery-results>=2.6.0",
|
||||||
"django-celery-beat>=2.9.0",
|
"django-celery-beat>=2.9.0",
|
||||||
]
|
]
|
||||||
@@ -63,12 +63,12 @@ prod = [
|
|||||||
"psycopg[c]>=3.3.4,<4.0.0",
|
"psycopg[c]>=3.3.4,<4.0.0",
|
||||||
]
|
]
|
||||||
dev = [
|
dev = [
|
||||||
"django-debug-toolbar>=8.0.0,<9",
|
"django-debug-toolbar>=7.1.1,<8",
|
||||||
"ipython>=9.17.1,<10.0.0",
|
"ipython>=9.16.1,<10.0.0",
|
||||||
"pre-commit>=4.6.1,<5.0.0",
|
"pre-commit>=4.6.0,<5.0.0",
|
||||||
"ruff>=0.16.6,<1.0.0",
|
"ruff>=0.16.0,<1.0.0",
|
||||||
"djhtml>=3.0.11,<4.0.0",
|
"djhtml>=3.0.11,<4.0.0",
|
||||||
"faker>=40.38.0,<41.0.0",
|
"faker>=40.37.0,<41.0.0",
|
||||||
"rjsmin>=1.2.5,<2.0.0",
|
"rjsmin>=1.2.5,<2.0.0",
|
||||||
]
|
]
|
||||||
tests = [
|
tests = [
|
||||||
@@ -78,7 +78,7 @@ tests = [
|
|||||||
"pytest-django>=4.14.0,<5.0.0",
|
"pytest-django>=4.14.0,<5.0.0",
|
||||||
"model-bakery>=1.24.0,<2.0.0",
|
"model-bakery>=1.24.0,<2.0.0",
|
||||||
"beautifulsoup4>=4.15.0,<5",
|
"beautifulsoup4>=4.15.0,<5",
|
||||||
"lxml>=6.1.3,<7",
|
"lxml>=6.1.2,<7",
|
||||||
]
|
]
|
||||||
docs = [
|
docs = [
|
||||||
"mkdocs>=1.6.1,<2.0.0",
|
"mkdocs>=1.6.1,<2.0.0",
|
||||||
@@ -132,13 +132,6 @@ ignore = [
|
|||||||
"RUF012" # mutable class attributes. This rule doesn't integrate well with django
|
"RUF012" # mutable class attributes. This rule doesn't integrate well with django
|
||||||
]
|
]
|
||||||
|
|
||||||
[tool.ruff.lint.per-file-ignores]
|
|
||||||
# schemas and API routes are built upon ninja and pydantic,
|
|
||||||
# which heavily rely on type annotations at runtime.
|
|
||||||
# Systematically using TYPE_CHECKING blocks in those files is NOT safe
|
|
||||||
"schemas.py" = ["TCH"]
|
|
||||||
"api.py" = ["TCH"]
|
|
||||||
|
|
||||||
[tool.ruff.lint.pydocstyle]
|
[tool.ruff.lint.pydocstyle]
|
||||||
convention = "google"
|
convention = "google"
|
||||||
|
|
||||||
|
|||||||
@@ -1,8 +1,8 @@
|
|||||||
from datetime import datetime, timedelta
|
from datetime import datetime, timedelta
|
||||||
from typing import TYPE_CHECKING
|
|
||||||
|
|
||||||
import pytest
|
import pytest
|
||||||
from django.contrib.auth.models import Permission
|
from django.contrib.auth.models import Permission
|
||||||
|
from django.test import Client
|
||||||
from django.urls import reverse
|
from django.urls import reverse
|
||||||
from django.utils.timezone import localtime
|
from django.utils.timezone import localtime
|
||||||
from model_bakery import baker
|
from model_bakery import baker
|
||||||
@@ -10,9 +10,6 @@ from pytest_django.asserts import assertRedirects
|
|||||||
|
|
||||||
from core.models import BanGroup, User, UserBan
|
from core.models import BanGroup, User, UserBan
|
||||||
|
|
||||||
if TYPE_CHECKING:
|
|
||||||
from django.test import Client
|
|
||||||
|
|
||||||
|
|
||||||
@pytest.fixture
|
@pytest.fixture
|
||||||
def operator(db) -> User:
|
def operator(db) -> User:
|
||||||
|
|||||||
+1
-2
@@ -9,6 +9,7 @@ from django.utils.timezone import get_current_timezone
|
|||||||
from django.utils.translation import gettext_lazy as _
|
from django.utils.translation import gettext_lazy as _
|
||||||
from PIL import Image
|
from PIL import Image
|
||||||
|
|
||||||
|
from core.models import User
|
||||||
from core.utils import resize_image
|
from core.utils import resize_image
|
||||||
from core.views import MultipleImageField
|
from core.views import MultipleImageField
|
||||||
from core.views.forms import SelectDate
|
from core.views.forms import SelectDate
|
||||||
@@ -19,8 +20,6 @@ from sas.widgets.ajax_select import AutoCompleteSelectAlbum
|
|||||||
if TYPE_CHECKING:
|
if TYPE_CHECKING:
|
||||||
from django.db.models.fields.files import FieldFile
|
from django.db.models.fields.files import FieldFile
|
||||||
|
|
||||||
from core.models import User
|
|
||||||
|
|
||||||
|
|
||||||
class AlbumCreateForm(forms.ModelForm):
|
class AlbumCreateForm(forms.ModelForm):
|
||||||
class Meta:
|
class Meta:
|
||||||
|
|||||||
@@ -1,13 +1,14 @@
|
|||||||
import random
|
import random
|
||||||
import string
|
import string
|
||||||
from pathlib import Path
|
from pathlib import Path
|
||||||
from typing import TYPE_CHECKING, Callable
|
from typing import Callable
|
||||||
from unittest.mock import patch
|
from unittest.mock import patch
|
||||||
|
|
||||||
import pytest
|
import pytest
|
||||||
from django.conf import settings
|
from django.conf import settings
|
||||||
from django.core.files.base import ContentFile
|
from django.core.files.base import ContentFile
|
||||||
from django.core.files.uploadedfile import SimpleUploadedFile
|
from django.core.files.uploadedfile import SimpleUploadedFile
|
||||||
|
from django.test import Client
|
||||||
from django.urls import reverse
|
from django.urls import reverse
|
||||||
from django.utils.datastructures import MultiValueDict
|
from django.utils.datastructures import MultiValueDict
|
||||||
from django.utils.timezone import localdate
|
from django.utils.timezone import localdate
|
||||||
@@ -22,9 +23,6 @@ from sas.baker_recipes import picture_recipe
|
|||||||
from sas.forms import AlbumEditForm
|
from sas.forms import AlbumEditForm
|
||||||
from sas.models import Album
|
from sas.models import Album
|
||||||
|
|
||||||
if TYPE_CHECKING:
|
|
||||||
from django.test import Client
|
|
||||||
|
|
||||||
|
|
||||||
@pytest.fixture
|
@pytest.fixture
|
||||||
def sas_root(db) -> Album:
|
def sas_root(db) -> Album:
|
||||||
|
|||||||
+2
-4
@@ -12,7 +12,7 @@
|
|||||||
# OR WITHIN THE LOCAL FILE "LICENSE"
|
# OR WITHIN THE LOCAL FILE "LICENSE"
|
||||||
#
|
#
|
||||||
#
|
#
|
||||||
from typing import TYPE_CHECKING, Any
|
from typing import Any
|
||||||
|
|
||||||
from django.conf import settings
|
from django.conf import settings
|
||||||
from django.contrib.auth.mixins import PermissionRequiredMixin
|
from django.contrib.auth.mixins import PermissionRequiredMixin
|
||||||
@@ -21,6 +21,7 @@ from django.db.models import Count, OuterRef, Subquery
|
|||||||
from django.http import Http404, HttpResponseRedirect
|
from django.http import Http404, HttpResponseRedirect
|
||||||
from django.shortcuts import get_object_or_404, redirect
|
from django.shortcuts import get_object_or_404, redirect
|
||||||
from django.urls import reverse
|
from django.urls import reverse
|
||||||
|
from django.utils.safestring import SafeString
|
||||||
from django.views.generic import CreateView, DetailView, TemplateView
|
from django.views.generic import CreateView, DetailView, TemplateView
|
||||||
from django.views.generic.edit import FormView, UpdateView
|
from django.views.generic.edit import FormView, UpdateView
|
||||||
|
|
||||||
@@ -39,9 +40,6 @@ from sas.forms import (
|
|||||||
)
|
)
|
||||||
from sas.models import Album, PeoplePictureRelation, Picture
|
from sas.models import Album, PeoplePictureRelation, Picture
|
||||||
|
|
||||||
if TYPE_CHECKING:
|
|
||||||
from django.utils.safestring import SafeString
|
|
||||||
|
|
||||||
|
|
||||||
class AlbumCreateFragment(FragmentMixin, CreateView):
|
class AlbumCreateFragment(FragmentMixin, CreateView):
|
||||||
model = Album
|
model = Album
|
||||||
|
|||||||
+1
-4
@@ -2,15 +2,12 @@ import logging
|
|||||||
import signal
|
import signal
|
||||||
import subprocess
|
import subprocess
|
||||||
import sys
|
import sys
|
||||||
from typing import TYPE_CHECKING
|
from pathlib import Path
|
||||||
|
|
||||||
import psutil
|
import psutil
|
||||||
|
|
||||||
from sith import settings
|
from sith import settings
|
||||||
|
|
||||||
if TYPE_CHECKING:
|
|
||||||
from pathlib import Path
|
|
||||||
|
|
||||||
|
|
||||||
def get_pid_file(procfile: Path) -> Path:
|
def get_pid_file(procfile: Path) -> Path:
|
||||||
"""Get the PID file associated with a procfile"""
|
"""Get the PID file associated with a procfile"""
|
||||||
|
|||||||
+2
-5
@@ -1,13 +1,10 @@
|
|||||||
from contextlib import nullcontext as does_not_raise
|
from contextlib import nullcontext as does_not_raise
|
||||||
from typing import TYPE_CHECKING
|
|
||||||
|
|
||||||
import pytest
|
import pytest
|
||||||
from django.test.utils import override_settings
|
|
||||||
from django.urls import reverse
|
|
||||||
|
|
||||||
if TYPE_CHECKING:
|
|
||||||
from _pytest.raises import RaisesExc
|
from _pytest.raises import RaisesExc
|
||||||
from django.test import Client
|
from django.test import Client
|
||||||
|
from django.test.utils import override_settings
|
||||||
|
from django.urls import reverse
|
||||||
|
|
||||||
|
|
||||||
@pytest.mark.django_db
|
@pytest.mark.django_db
|
||||||
|
|||||||
@@ -1,17 +1,14 @@
|
|||||||
from pathlib import Path
|
from pathlib import Path
|
||||||
from typing import TYPE_CHECKING
|
|
||||||
|
|
||||||
from django.conf import settings
|
from django.conf import settings
|
||||||
from django.contrib.staticfiles.finders import find
|
from django.contrib.staticfiles.finders import find
|
||||||
from django.contrib.staticfiles.storage import (
|
from django.contrib.staticfiles.storage import (
|
||||||
ManifestStaticFilesStorage,
|
ManifestStaticFilesStorage,
|
||||||
)
|
)
|
||||||
|
from django.core.files.storage import Storage
|
||||||
|
|
||||||
from staticfiles.processors import JS, JSBundler, Scss
|
from staticfiles.processors import JS, JSBundler, Scss
|
||||||
|
|
||||||
if TYPE_CHECKING:
|
|
||||||
from django.core.files.storage import Storage
|
|
||||||
|
|
||||||
|
|
||||||
class ManifestPostProcessingStorage(ManifestStaticFilesStorage):
|
class ManifestPostProcessingStorage(ManifestStaticFilesStorage):
|
||||||
def url(self, name: str, *, force: bool = False) -> str:
|
def url(self, name: str, *, force: bool = False) -> str:
|
||||||
|
|||||||
@@ -1,10 +1,6 @@
|
|||||||
# Generated by Django 5.2.3 on 2025-09-08 05:38
|
# Generated by Django 5.2.3 on 2025-09-08 05:38
|
||||||
|
|
||||||
from typing import TYPE_CHECKING
|
|
||||||
|
|
||||||
from django.db import migrations, models
|
from django.db import migrations, models
|
||||||
|
|
||||||
if TYPE_CHECKING:
|
|
||||||
from django.db.migrations.state import StateApps
|
from django.db.migrations.state import StateApps
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -1,16 +1,12 @@
|
|||||||
# Generated by Django 5.2.17 on 2026-09-01 08:44
|
# Generated by Django 5.2.17 on 2026-09-01 08:44
|
||||||
|
|
||||||
from typing import TYPE_CHECKING
|
|
||||||
|
|
||||||
import django.utils.timezone
|
import django.utils.timezone
|
||||||
from django.db import migrations, models
|
from django.db import migrations, models
|
||||||
|
from django.db.migrations.state import StateApps
|
||||||
from django.db.models import F, Value
|
from django.db.models import F, Value
|
||||||
from django.db.models.functions import Least
|
from django.db.models.functions import Least
|
||||||
from django.utils.timezone import now
|
from django.utils.timezone import now
|
||||||
|
|
||||||
if TYPE_CHECKING:
|
|
||||||
from django.db.migrations.state import StateApps
|
|
||||||
|
|
||||||
|
|
||||||
def make_default_creation_date(apps: StateApps, schema_editor):
|
def make_default_creation_date(apps: StateApps, schema_editor):
|
||||||
Subscription = apps.get_model("subscription", "Subscription")
|
Subscription = apps.get_model("subscription", "Subscription")
|
||||||
|
|||||||
@@ -1,12 +1,13 @@
|
|||||||
"""Tests focused on testing subscription creation"""
|
"""Tests focused on testing subscription creation"""
|
||||||
|
|
||||||
from datetime import date, timedelta
|
from datetime import date, timedelta
|
||||||
from typing import TYPE_CHECKING, Callable
|
from typing import Callable
|
||||||
|
|
||||||
import pytest
|
import pytest
|
||||||
from dateutil.relativedelta import relativedelta
|
from dateutil.relativedelta import relativedelta
|
||||||
from django.conf import settings
|
from django.conf import settings
|
||||||
from django.contrib.auth.models import Permission
|
from django.contrib.auth.models import Permission
|
||||||
|
from django.test import Client
|
||||||
from django.urls import reverse
|
from django.urls import reverse
|
||||||
from django.utils.timezone import localdate
|
from django.utils.timezone import localdate
|
||||||
from model_bakery import baker
|
from model_bakery import baker
|
||||||
@@ -18,9 +19,6 @@ from counter.models import Customer
|
|||||||
from subscription.forms import SubscriptionExistingUserForm, SubscriptionNewUserForm
|
from subscription.forms import SubscriptionExistingUserForm, SubscriptionNewUserForm
|
||||||
from subscription.models import Subscription
|
from subscription.models import Subscription
|
||||||
|
|
||||||
if TYPE_CHECKING:
|
|
||||||
from django.test import Client
|
|
||||||
|
|
||||||
|
|
||||||
@pytest.mark.django_db
|
@pytest.mark.django_db
|
||||||
@pytest.mark.parametrize(
|
@pytest.mark.parametrize(
|
||||||
|
|||||||
Reference in New Issue
Block a user