mirror of
https://github.com/ae-utbm/sith.git
synced 2026-06-27 02:12:40 +00:00
Merge pull request #1439 from ae-utbm/taiste
AEMark, max account balance, membership API and bugfixes
This commit is contained in:
@@ -1,7 +1,7 @@
|
|||||||
repos:
|
repos:
|
||||||
- repo: https://github.com/astral-sh/ruff-pre-commit
|
- repo: https://github.com/astral-sh/ruff-pre-commit
|
||||||
# Ruff version.
|
# Ruff version.
|
||||||
rev: v0.15.13
|
rev: v0.15.19
|
||||||
hooks:
|
hooks:
|
||||||
- id: ruff-check # just check the code, and print the errors
|
- id: ruff-check # just check the code, and print the errors
|
||||||
- id: ruff-check # actually fix the fixable errors, but print nothing
|
- id: ruff-check # actually fix the fixable errors, but print nothing
|
||||||
@@ -12,7 +12,7 @@ repos:
|
|||||||
rev: v0.6.1
|
rev: v0.6.1
|
||||||
hooks:
|
hooks:
|
||||||
- id: biome-check
|
- id: biome-check
|
||||||
additional_dependencies: ["@biomejs/biome@2.4.6"]
|
additional_dependencies: ["@biomejs/biome@2.5.1"]
|
||||||
- repo: https://github.com/rtts/djhtml
|
- repo: https://github.com/rtts/djhtml
|
||||||
rev: 3.0.11
|
rev: 3.0.11
|
||||||
hooks:
|
hooks:
|
||||||
|
|||||||
+1
-1
@@ -17,7 +17,7 @@
|
|||||||
"linter": {
|
"linter": {
|
||||||
"enabled": true,
|
"enabled": true,
|
||||||
"rules": {
|
"rules": {
|
||||||
"recommended": true,
|
"preset": "recommended",
|
||||||
"style": {
|
"style": {
|
||||||
"useNamingConvention": "error"
|
"useNamingConvention": "error"
|
||||||
},
|
},
|
||||||
|
|||||||
+41
@@ -11,6 +11,7 @@ from club.models import Club, Membership
|
|||||||
from club.schemas import (
|
from club.schemas import (
|
||||||
ClubSchema,
|
ClubSchema,
|
||||||
ClubSearchFilterSchema,
|
ClubSearchFilterSchema,
|
||||||
|
MembershipFilterSchema,
|
||||||
SimpleClubSchema,
|
SimpleClubSchema,
|
||||||
UserMembershipSchema,
|
UserMembershipSchema,
|
||||||
)
|
)
|
||||||
@@ -62,3 +63,43 @@ class UserClubController(ControllerBase):
|
|||||||
.filter(user=user)
|
.filter(user=user)
|
||||||
.select_related("club", "user", "role")
|
.select_related("club", "user", "role")
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
|
@api_controller("/clubs/members/")
|
||||||
|
class ClubMembershipController(ControllerBase):
|
||||||
|
@route.get(
|
||||||
|
"/new",
|
||||||
|
response=list[UserMembershipSchema],
|
||||||
|
auth=[ApiKeyAuth(), SessionAuth()],
|
||||||
|
permissions=[HasPerm("club.view_club")],
|
||||||
|
url_name="get_new_clubs_members_since_date",
|
||||||
|
)
|
||||||
|
def fetch_new_club_members(self, filters: Query[MembershipFilterSchema]):
|
||||||
|
"""give all the members of all clubs that have joined since a given date"""
|
||||||
|
memberships = (
|
||||||
|
Membership.objects.ongoing()
|
||||||
|
.filter(start_date__gte=filters.since_date, end_date__isnull=True)
|
||||||
|
.select_related("user", "role", "club")
|
||||||
|
)
|
||||||
|
if filters.clubs_id:
|
||||||
|
memberships = memberships.filter(club_id__in=filters.clubs_id)
|
||||||
|
|
||||||
|
return memberships.order_by("start_date")
|
||||||
|
|
||||||
|
@route.get(
|
||||||
|
"/former",
|
||||||
|
response=list[UserMembershipSchema],
|
||||||
|
auth=[ApiKeyAuth(), SessionAuth()],
|
||||||
|
permissions=[HasPerm("club.view_club")],
|
||||||
|
url_name="get_former_clubs_members_since_date",
|
||||||
|
)
|
||||||
|
def fetch_former_club_members(self, filters: Query[MembershipFilterSchema]):
|
||||||
|
"""give all the former members of all clubs that have left since a given date"""
|
||||||
|
memberships = Membership.objects.filter(
|
||||||
|
start_date__lt=filters.since_date,
|
||||||
|
end_date__gte=filters.since_date,
|
||||||
|
).select_related("user", "role", "club")
|
||||||
|
if filters.clubs_id:
|
||||||
|
memberships = memberships.filter(club_id__in=filters.clubs_id)
|
||||||
|
|
||||||
|
return memberships.order_by("start_date")
|
||||||
|
|||||||
@@ -1,3 +1,4 @@
|
|||||||
|
from datetime import date
|
||||||
from typing import Annotated
|
from typing import Annotated
|
||||||
|
|
||||||
from django.db.models import Q
|
from django.db.models import Q
|
||||||
@@ -79,3 +80,9 @@ class UserMembershipSchema(ModelSchema):
|
|||||||
|
|
||||||
club: SimpleClubSchema
|
club: SimpleClubSchema
|
||||||
role: ClubRoleSchema
|
role: ClubRoleSchema
|
||||||
|
user: SimpleUserSchema
|
||||||
|
|
||||||
|
|
||||||
|
class MembershipFilterSchema(FilterSchema):
|
||||||
|
since_date: Annotated[date, FilterLookup("date__lte")]
|
||||||
|
clubs_id: set[int] | None = None
|
||||||
|
|||||||
@@ -45,3 +45,10 @@
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@media screen and (max-width: 575px){
|
||||||
|
#club-list{
|
||||||
|
padding-left: 0;
|
||||||
|
padding-right: 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|||||||
@@ -0,0 +1,203 @@
|
|||||||
|
from datetime import timedelta
|
||||||
|
|
||||||
|
from django.contrib.auth.models import Permission
|
||||||
|
from django.test import TestCase
|
||||||
|
from django.urls import reverse
|
||||||
|
from django.utils.timezone import localdate
|
||||||
|
from model_bakery import baker
|
||||||
|
|
||||||
|
from club.models import Club, ClubRole, Membership
|
||||||
|
from core.baker_recipes import subscriber_user
|
||||||
|
from core.models import User
|
||||||
|
|
||||||
|
|
||||||
|
class TestMembershipAPI(TestCase):
|
||||||
|
@classmethod
|
||||||
|
def setUpTestData(cls):
|
||||||
|
cls.user = baker.make(User)
|
||||||
|
perm = Permission.objects.get(codename="view_club")
|
||||||
|
cls.user.user_permissions.add(perm)
|
||||||
|
cls.clubs = baker.make(Club, _quantity=3, is_active=True)
|
||||||
|
cls.roles = baker.make(ClubRole, _quantity=3, is_active=True)
|
||||||
|
cls.expectedNumQueries = 5
|
||||||
|
|
||||||
|
# Clean existing data to avoid side effects
|
||||||
|
Membership.objects.all().delete()
|
||||||
|
|
||||||
|
cls.memberships = [
|
||||||
|
# on going
|
||||||
|
Membership.objects.create(
|
||||||
|
club=cls.clubs[0],
|
||||||
|
user=subscriber_user.make(),
|
||||||
|
role=cls.roles[0],
|
||||||
|
start_date=localdate() - timedelta(weeks=1),
|
||||||
|
),
|
||||||
|
# on going
|
||||||
|
Membership.objects.create(
|
||||||
|
club=cls.clubs[1],
|
||||||
|
user=subscriber_user.make(),
|
||||||
|
role=cls.roles[1],
|
||||||
|
start_date=localdate() - timedelta(days=1),
|
||||||
|
),
|
||||||
|
# former
|
||||||
|
Membership.objects.create(
|
||||||
|
club=cls.clubs[1],
|
||||||
|
user=subscriber_user.make(),
|
||||||
|
role=cls.roles[2],
|
||||||
|
start_date=localdate() - timedelta(weeks=2),
|
||||||
|
end_date=localdate() - timedelta(days=6),
|
||||||
|
),
|
||||||
|
# on going
|
||||||
|
Membership.objects.create(
|
||||||
|
club=cls.clubs[2],
|
||||||
|
user=subscriber_user.make(),
|
||||||
|
role=cls.roles[0],
|
||||||
|
start_date=localdate() - timedelta(weeks=3),
|
||||||
|
),
|
||||||
|
# former
|
||||||
|
Membership.objects.create(
|
||||||
|
club=cls.clubs[1],
|
||||||
|
user=subscriber_user.make(),
|
||||||
|
role=cls.roles[2],
|
||||||
|
start_date=localdate() - timedelta(days=4),
|
||||||
|
end_date=localdate() - timedelta(days=3),
|
||||||
|
),
|
||||||
|
# on going
|
||||||
|
Membership.objects.create(
|
||||||
|
club=cls.clubs[2],
|
||||||
|
user=subscriber_user.make(),
|
||||||
|
role=cls.roles[0],
|
||||||
|
start_date=localdate() - timedelta(days=1),
|
||||||
|
),
|
||||||
|
# former
|
||||||
|
Membership.objects.create(
|
||||||
|
club=cls.clubs[0],
|
||||||
|
user=subscriber_user.make(),
|
||||||
|
role=cls.roles[0],
|
||||||
|
start_date=localdate() - timedelta(weeks=6),
|
||||||
|
end_date=localdate() - timedelta(days=3),
|
||||||
|
),
|
||||||
|
# former
|
||||||
|
Membership.objects.create(
|
||||||
|
club=cls.clubs[2],
|
||||||
|
user=subscriber_user.make(),
|
||||||
|
role=cls.roles[0],
|
||||||
|
start_date=localdate() - timedelta(weeks=8),
|
||||||
|
end_date=localdate() - timedelta(days=6),
|
||||||
|
),
|
||||||
|
# former
|
||||||
|
Membership.objects.create(
|
||||||
|
club=cls.clubs[1],
|
||||||
|
user=subscriber_user.make(),
|
||||||
|
role=cls.roles[0],
|
||||||
|
start_date=localdate() - timedelta(weeks=8),
|
||||||
|
end_date=localdate() - timedelta(weeks=7, days=5),
|
||||||
|
),
|
||||||
|
]
|
||||||
|
|
||||||
|
|
||||||
|
class TestNewMembershipAPI(TestMembershipAPI):
|
||||||
|
@classmethod
|
||||||
|
def setUpTestData(cls):
|
||||||
|
super().setUpTestData()
|
||||||
|
cls.url = reverse("api:get_new_clubs_members_since_date")
|
||||||
|
|
||||||
|
def test_new_membership_one_club(self):
|
||||||
|
self.client.force_login(self.user)
|
||||||
|
since_date = localdate() - timedelta(weeks=1)
|
||||||
|
arg = {"since_date": since_date, "clubs_id": self.clubs[0].id}
|
||||||
|
with self.assertNumQueries(self.expectedNumQueries):
|
||||||
|
response = self.client.get(self.url, query_params=arg)
|
||||||
|
assert response.status_code == 200
|
||||||
|
data = response.json()
|
||||||
|
|
||||||
|
membership_ids = [e["id"] for e in data]
|
||||||
|
expected_ids = [self.memberships[0].id]
|
||||||
|
assert membership_ids == expected_ids
|
||||||
|
|
||||||
|
def test_new_membership_multiple_club(self):
|
||||||
|
self.client.force_login(self.user)
|
||||||
|
since_date = localdate() - timedelta(weeks=1)
|
||||||
|
arg = {
|
||||||
|
"since_date": since_date,
|
||||||
|
"clubs_id": [self.clubs[0].id, self.clubs[1].id],
|
||||||
|
}
|
||||||
|
with self.assertNumQueries(self.expectedNumQueries):
|
||||||
|
response = self.client.get(self.url, query_params=arg)
|
||||||
|
assert response.status_code == 200
|
||||||
|
data = response.json()
|
||||||
|
|
||||||
|
membership_ids = [e["id"] for e in data]
|
||||||
|
expected_ids = [self.memberships[0].id, self.memberships[1].id]
|
||||||
|
assert membership_ids == expected_ids
|
||||||
|
|
||||||
|
def test_new_membership_all_clubs(self):
|
||||||
|
self.client.force_login(self.user)
|
||||||
|
since_date = localdate() - timedelta(weeks=1)
|
||||||
|
arg = {"since_date": since_date}
|
||||||
|
with self.assertNumQueries(self.expectedNumQueries):
|
||||||
|
response = self.client.get(self.url, query_params=arg)
|
||||||
|
assert response.status_code == 200
|
||||||
|
data = response.json()
|
||||||
|
|
||||||
|
membership_ids = [e["id"] for e in data]
|
||||||
|
expected_ids = [
|
||||||
|
self.memberships[0].id,
|
||||||
|
self.memberships[1].id,
|
||||||
|
self.memberships[5].id,
|
||||||
|
]
|
||||||
|
assert membership_ids == expected_ids
|
||||||
|
|
||||||
|
|
||||||
|
class TestFormerMembershipAPI(TestMembershipAPI):
|
||||||
|
@classmethod
|
||||||
|
def setUpTestData(cls):
|
||||||
|
super().setUpTestData()
|
||||||
|
cls.url = reverse("api:get_former_clubs_members_since_date")
|
||||||
|
|
||||||
|
def test_former_membership_one_club(self):
|
||||||
|
self.client.force_login(self.user)
|
||||||
|
since_date = localdate() - timedelta(weeks=1)
|
||||||
|
arg = {"since_date": since_date, "clubs_id": self.clubs[1].id}
|
||||||
|
with self.assertNumQueries(self.expectedNumQueries):
|
||||||
|
response = self.client.get(self.url, query_params=arg)
|
||||||
|
|
||||||
|
assert response.status_code == 200
|
||||||
|
data = response.json()
|
||||||
|
|
||||||
|
membership_ids = [e["id"] for e in data]
|
||||||
|
expected_ids = [self.memberships[2].id]
|
||||||
|
assert membership_ids == expected_ids
|
||||||
|
|
||||||
|
def test_new_membership_multiple_club(self):
|
||||||
|
self.client.force_login(self.user)
|
||||||
|
since_date = localdate() - timedelta(weeks=1)
|
||||||
|
arg = {
|
||||||
|
"since_date": since_date,
|
||||||
|
"clubs_id": [self.clubs[1].id, self.clubs[0].id],
|
||||||
|
}
|
||||||
|
with self.assertNumQueries(self.expectedNumQueries):
|
||||||
|
response = self.client.get(self.url, query_params=arg)
|
||||||
|
assert response.status_code == 200
|
||||||
|
data = response.json()
|
||||||
|
|
||||||
|
membership_ids = [e["id"] for e in data]
|
||||||
|
expected_ids = [self.memberships[6].id, self.memberships[2].id]
|
||||||
|
assert membership_ids == expected_ids
|
||||||
|
|
||||||
|
def test_new_membership_all_clubs(self):
|
||||||
|
self.client.force_login(self.user)
|
||||||
|
since_date = localdate() - timedelta(weeks=1)
|
||||||
|
arg = {"since_date": since_date}
|
||||||
|
with self.assertNumQueries(self.expectedNumQueries):
|
||||||
|
response = self.client.get(self.url, query_params=arg)
|
||||||
|
assert response.status_code == 200
|
||||||
|
data = response.json()
|
||||||
|
|
||||||
|
membership_ids = [e["id"] for e in data]
|
||||||
|
expected_ids = [
|
||||||
|
self.memberships[7].id,
|
||||||
|
self.memberships[6].id,
|
||||||
|
self.memberships[2].id,
|
||||||
|
]
|
||||||
|
assert membership_ids == expected_ids
|
||||||
@@ -1,4 +1,5 @@
|
|||||||
import pytest
|
import pytest
|
||||||
|
from aemark import markdown
|
||||||
from bs4 import BeautifulSoup
|
from bs4 import BeautifulSoup
|
||||||
from django.test import Client
|
from django.test import Client
|
||||||
from django.urls import reverse
|
from django.urls import reverse
|
||||||
@@ -7,7 +8,6 @@ from pytest_django.asserts import assertHTMLEqual, 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
|
||||||
from core.markdown import markdown
|
|
||||||
from core.models import PageRev, User
|
from core.models import PageRev, User
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
+1
-1
@@ -1,13 +1,13 @@
|
|||||||
from datetime import datetime
|
from datetime import datetime
|
||||||
from typing import Annotated
|
from typing import Annotated
|
||||||
|
|
||||||
|
from aemark import markdown
|
||||||
from ninja import FilterLookup, FilterSchema, ModelSchema
|
from ninja import FilterLookup, FilterSchema, ModelSchema
|
||||||
from ninja_extra import service_resolver
|
from ninja_extra import service_resolver
|
||||||
from ninja_extra.context import RouteContext
|
from ninja_extra.context import RouteContext
|
||||||
|
|
||||||
from club.schemas import ClubProfileSchema
|
from club.schemas import ClubProfileSchema
|
||||||
from com.models import News, NewsDate
|
from com.models import News, NewsDate
|
||||||
from core.markdown import markdown
|
|
||||||
|
|
||||||
|
|
||||||
class NewsDateFilterSchema(FilterSchema):
|
class NewsDateFilterSchema(FilterSchema):
|
||||||
|
|||||||
@@ -2,6 +2,7 @@ from datetime import timedelta
|
|||||||
from pathlib import Path
|
from pathlib import Path
|
||||||
|
|
||||||
import pytest
|
import pytest
|
||||||
|
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.http import HttpResponse
|
||||||
@@ -13,7 +14,6 @@ from pytest_django.asserts import assertNumQueries
|
|||||||
|
|
||||||
from com.ics_calendar import IcsCalendar
|
from com.ics_calendar import IcsCalendar
|
||||||
from com.models import News, NewsDate
|
from com.models import News, NewsDate
|
||||||
from core.markdown import markdown
|
|
||||||
from core.models import User
|
from core.models import User
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
+35
-36
@@ -2,12 +2,9 @@
|
|||||||
<h1>Markdown-AE Documentation</h1>
|
<h1>Markdown-AE Documentation</h1>
|
||||||
<p>Le Markdown le plus standard se trouve documenté ici:
|
<p>Le Markdown le plus standard se trouve documenté ici:
|
||||||
<a href="https://www.markdownguide.org/basic-syntax">https://www.markdownguide.org/basic-syntax</a>.<br />
|
<a href="https://www.markdownguide.org/basic-syntax">https://www.markdownguide.org/basic-syntax</a>.<br />
|
||||||
Si cette page n'est pas exhaustive vis à vis de la syntaxe du site AE,
|
Si cette page n’est pas exhaustive vis à vis de la syntaxe du site AE,
|
||||||
elle a au moins le mérite de bien documenter le Markdown original.</p>
|
elle a au moins le mérite de bien documenter le Markdown original.</p>
|
||||||
<p>Le réel parseur du site AE est une version tunée de <a href="https://github.com/lepture/mistune">mistune</a>.<br />
|
<p>Le réel parseur du site AE est une version tunée de <a href="https://github.com/kivikakk/comrak">comrak</a>.</p>
|
||||||
Les plus aventureux pourront aller lire ses <a href="https://github.com/lepture/mistune/blob/master/tests/fixtures">tests</a>
|
|
||||||
afin d'en connaître la syntaxe le plus finement possible.<br />
|
|
||||||
En pratique, cette page devrait déjà résumer une bonne partie.</p>
|
|
||||||
<h2>Basique</h2>
|
<h2>Basique</h2>
|
||||||
<ul>
|
<ul>
|
||||||
<li>Mettre le texte en <strong>gras</strong> : <code>**texte**</code></li>
|
<li>Mettre le texte en <strong>gras</strong> : <code>**texte**</code></li>
|
||||||
@@ -15,8 +12,8 @@ En pratique, cette page devrait déjà résumer une bonne partie.</p>
|
|||||||
<li><u>Souligner</u> le texte : <code>__texte__</code></li>
|
<li><u>Souligner</u> le texte : <code>__texte__</code></li>
|
||||||
<li><del>Barrer du texte</del> : <code>~~texte~~</code></li>
|
<li><del>Barrer du texte</del> : <code>~~texte~~</code></li>
|
||||||
<li>On peut bien sûr tout <del><em><strong><u>combiner</u></strong></em></del> : <code>~~***__texte__***~~</code></li>
|
<li>On peut bien sûr tout <del><em><strong><u>combiner</u></strong></em></del> : <code>~~***__texte__***~~</code></li>
|
||||||
<li>Mettre du texte^en exposant^ : <code><sup>texte</sup></code></li>
|
<li>Mettre du texte<sup>en exposant</sup> : <code><sup>texte</sup></code></li>
|
||||||
<li>Mettre du texte~en indice~ : <code><sub>texte</sub></code></li>
|
<li>Mettre du texte<sub>en indice</sub> : <code><sub>texte</sub></code></li>
|
||||||
</ul>
|
</ul>
|
||||||
<h2>Liens</h2>
|
<h2>Liens</h2>
|
||||||
<ul>
|
<ul>
|
||||||
@@ -28,10 +25,10 @@ En pratique, cette page devrait déjà résumer une bonne partie.</p>
|
|||||||
</ul>
|
</ul>
|
||||||
<p><a href="http://www.site.com">nom du lien</a></p>
|
<p><a href="http://www.site.com">nom du lien</a></p>
|
||||||
<ul>
|
<ul>
|
||||||
<li>Les liens peuvent être internes au site de l'AE, on peut dès lors éviter d'entrer
|
<li>Les liens peuvent être internes au site de l’AE, on peut dès lors éviter d’entrer
|
||||||
l'adresse complète d'une page : <code>[nom du lien](page://nomDeLaPage)</code></li>
|
l’adresse complète d’une page : <code>[nom du lien](page://nomDeLaPage)</code></li>
|
||||||
</ul>
|
</ul>
|
||||||
<p><a href="/page/nomDeLaPage/">nom du lien</a></p>
|
<p><a href="/page/nomDeLaPage">nom du lien</a></p>
|
||||||
<ul>
|
<ul>
|
||||||
<li>On peut également utiliser une image pour les liens :
|
<li>On peut également utiliser une image pour les liens :
|
||||||
<code>[nom du lien](options)</code></li>
|
<code>[nom du lien](options)</code></li>
|
||||||
@@ -94,25 +91,25 @@ etc...
|
|||||||
<table>
|
<table>
|
||||||
<thead>
|
<thead>
|
||||||
<tr>
|
<tr>
|
||||||
<th>Titre</th>
|
<th>Titre</th>
|
||||||
<th>Titre2</th>
|
<th>Titre2</th>
|
||||||
<th>Titre3</th>
|
<th>Titre3</th>
|
||||||
</tr>
|
</tr>
|
||||||
</thead>
|
</thead>
|
||||||
<tbody>
|
<tbody>
|
||||||
<tr>
|
<tr>
|
||||||
<td>test</td>
|
<td>test</td>
|
||||||
<td>test</td>
|
<td>test</td>
|
||||||
<td>test</td>
|
<td>test</td>
|
||||||
</tr>
|
</tr>
|
||||||
<tr>
|
<tr>
|
||||||
<td>test</td>
|
<td>test</td>
|
||||||
<td>test</td>
|
<td>test</td>
|
||||||
<td>test</td>
|
<td>test</td>
|
||||||
</tr>
|
</tr>
|
||||||
</tbody>
|
</tbody>
|
||||||
</table>
|
</table>
|
||||||
<p>L'alignement dans les cellules est géré comme suit, avec les ':' sur la ligne en dessous du titre:</p>
|
<p>L’alignement dans les cellules est géré comme suit, avec les ‘:’ sur la ligne en dessous du titre:</p>
|
||||||
<pre><code>| Titre | Titre2 | Titre3 |
|
<pre><code>| Titre | Titre2 | Titre3 |
|
||||||
|:-------|:------:|-------:|
|
|:-------|:------:|-------:|
|
||||||
| gauche | centre | droite |
|
| gauche | centre | droite |
|
||||||
@@ -120,16 +117,16 @@ etc...
|
|||||||
<table>
|
<table>
|
||||||
<thead>
|
<thead>
|
||||||
<tr>
|
<tr>
|
||||||
<th style="text-align:left">Titre</th>
|
<th align="left">Titre</th>
|
||||||
<th style="text-align:center">Titre2</th>
|
<th align="center">Titre2</th>
|
||||||
<th style="text-align:right">Titre3</th>
|
<th align="right">Titre3</th>
|
||||||
</tr>
|
</tr>
|
||||||
</thead>
|
</thead>
|
||||||
<tbody>
|
<tbody>
|
||||||
<tr>
|
<tr>
|
||||||
<td style="text-align:left">gauche</td>
|
<td align="left">gauche</td>
|
||||||
<td style="text-align:center">centre</td>
|
<td align="center">centre</td>
|
||||||
<td style="text-align:right">droite</td>
|
<td align="right">droite</td>
|
||||||
</tr>
|
</tr>
|
||||||
</tbody>
|
</tbody>
|
||||||
</table>
|
</table>
|
||||||
@@ -141,11 +138,11 @@ etc...
|
|||||||

|

|
||||||

|

|
||||||
</code></pre>
|
</code></pre>
|
||||||
<p><img src="/static/core/img/logo.png" alt="image à 50%" title="Image à 50%" style="width:50%;" /><br />
|
<p><img src="/static/core/img/logo.png" style="width:50%" alt="image à 50%" title="Image à 50%" /><br />
|
||||||
Image à 50% de la largeur de la page.</p>
|
Image à 50% de la largeur de la page.</p>
|
||||||
<p><img src="/static/core/img/logo.png" alt="image de 350 pixels de large" title="Image de 350 pixels" style="width:350px;" /><br />
|
<p><img src="/static/core/img/logo.png" style="width:350px" alt="image de 350 pixels de large" title="Image de 350 pixels" /><br />
|
||||||
Image de 350 pixels de large.</p>
|
Image de 350 pixels de large.</p>
|
||||||
<p><img src="/static/core/img/logo.png" alt="image de 350x100 pixels" title="Image de 350x100 pixels" style="width:350px;height:100px;" /><br />
|
<p><img src="/static/core/img/logo.png" style="width:350px;height:100px" alt="image de 350x100 pixels" title="Image de 350x100 pixels" /><br />
|
||||||
Image de 350x100 pixels.</p>
|
Image de 350x100 pixels.</p>
|
||||||
<p>(devrait pouvoir détecter si vidéo ou non)</p>
|
<p>(devrait pouvoir détecter si vidéo ou non)</p>
|
||||||
<h2>Blocs de citations</h2>
|
<h2>Blocs de citations</h2>
|
||||||
@@ -159,9 +156,9 @@ Image de 350x100 pixels.</p>
|
|||||||
un bloc de
|
un bloc de
|
||||||
citation</p>
|
citation</p>
|
||||||
</blockquote>
|
</blockquote>
|
||||||
<p>Il est possible d'intégrer de la syntaxe Markdown-AE dans un tel bloc.</p>
|
<p>Il est possible d’intégrer de la syntaxe Markdown-AE dans un tel bloc.</p>
|
||||||
<h2>Note de bas de page</h2>
|
<h2>Note de bas de page</h2>
|
||||||
<p>On les crée comme ça<sup class="footnote-ref" id="fnref-1"><a href="#fn-1">1</a></sup>:</p>
|
<p>On les crée comme ça<sup class="footnote-ref"><a href="#fn-key" id="fnref-key" data-footnote-ref>1</a></sup>:</p>
|
||||||
<pre><code>Je fais une note[^clef].
|
<pre><code>Je fais une note[^clef].
|
||||||
|
|
||||||
[^clef]: je note ensuite où je veux le contenu de ma clef qui apparaîtra quand même en bas
|
[^clef]: je note ensuite où je veux le contenu de ma clef qui apparaîtra quand même en bas
|
||||||
@@ -175,13 +172,15 @@ citation</p>
|
|||||||
</code></pre>
|
</code></pre>
|
||||||
<h2>Échapper des caractères</h2>
|
<h2>Échapper des caractères</h2>
|
||||||
<ul>
|
<ul>
|
||||||
<li>Il est possible d'ignorer un caractère spécial en l'échappant à l'aide d'un \</li>
|
<li>Il est possible d’ignorer un caractère spécial en l’échappant à l’aide d’un \</li>
|
||||||
<li>L'échappement de blocs de codes complet se fera à l'aide de balises <nosyntax></nosyntax></li>
|
<li>L’échappement de blocs de codes complet se fera à l’aide de balises <nosyntax></nosyntax></li>
|
||||||
</ul>
|
</ul>
|
||||||
<h2>Autres (hérité de l'ancien wiki)</h2>
|
<h2>Autres (hérité de l’ancien wiki)</h2>
|
||||||
<p>Une ligne peut être créée avec une ligne contenant 4 tirets (<code>----</code>).</p>
|
<p>Une ligne peut être créée avec une ligne contenant 4 tirets (<code>----</code>).</p>
|
||||||
<section class="footnotes">
|
<section class="footnotes" data-footnotes>
|
||||||
<ol>
|
<ol>
|
||||||
<li id="fn-1"><p>ceci est le contenu de ma clef<a href="#fnref-1" class="footnote">↩</a></p></li>
|
<li id="fn-key">
|
||||||
|
<p>ceci est le contenu de ma clef <a href="#fnref-key" class="footnote-backref" data-footnote-backref data-footnote-backref-idx="1" aria-label="Back to reference 1">↩</a></p>
|
||||||
|
</li>
|
||||||
</ol>
|
</ol>
|
||||||
</section>
|
</section>
|
||||||
|
|||||||
@@ -7,10 +7,7 @@ https://www.markdownguide.org/basic-syntax.
|
|||||||
Si cette page n'est pas exhaustive vis à vis de la syntaxe du site AE,
|
Si cette page n'est pas exhaustive vis à vis de la syntaxe du site AE,
|
||||||
elle a au moins le mérite de bien documenter le Markdown original.
|
elle a au moins le mérite de bien documenter le Markdown original.
|
||||||
|
|
||||||
Le réel parseur du site AE est une version tunée de [mistune](https://github.com/lepture/mistune).
|
Le réel parseur du site AE est une version tunée de [comrak](https://github.com/kivikakk/comrak).
|
||||||
Les plus aventureux pourront aller lire ses [tests](https://github.com/lepture/mistune/blob/master/tests/fixtures)
|
|
||||||
afin d'en connaître la syntaxe le plus finement possible.
|
|
||||||
En pratique, cette page devrait déjà résumer une bonne partie.
|
|
||||||
|
|
||||||
## Basique
|
## Basique
|
||||||
|
|
||||||
|
|||||||
@@ -22,11 +22,10 @@
|
|||||||
#
|
#
|
||||||
|
|
||||||
|
|
||||||
|
from aemark import markdown
|
||||||
from django.conf import settings
|
from django.conf import settings
|
||||||
from django.core.management.base import BaseCommand
|
from django.core.management.base import BaseCommand
|
||||||
|
|
||||||
from core.markdown import markdown
|
|
||||||
|
|
||||||
|
|
||||||
class Command(BaseCommand):
|
class Command(BaseCommand):
|
||||||
help = "Output the fully rendered SYNTAX.md file"
|
help = "Output the fully rendered SYNTAX.md file"
|
||||||
|
|||||||
@@ -1,132 +0,0 @@
|
|||||||
#
|
|
||||||
# Copyright 2023 © AE UTBM
|
|
||||||
# ae@utbm.fr / ae.info@utbm.fr
|
|
||||||
#
|
|
||||||
# This file is part of the website of the UTBM Student Association (AE UTBM),
|
|
||||||
# https://ae.utbm.fr.
|
|
||||||
#
|
|
||||||
# You can find the source code of the website at https://github.com/ae-utbm/sith
|
|
||||||
#
|
|
||||||
# LICENSED UNDER THE GNU GENERAL PUBLIC LICENSE VERSION 3 (GPLv3)
|
|
||||||
# SEE : https://raw.githubusercontent.com/ae-utbm/sith/master/LICENSE
|
|
||||||
# OR WITHIN THE LOCAL FILE "LICENSE"
|
|
||||||
#
|
|
||||||
#
|
|
||||||
from __future__ import annotations
|
|
||||||
|
|
||||||
import re
|
|
||||||
from typing import TYPE_CHECKING
|
|
||||||
|
|
||||||
import mistune
|
|
||||||
from django.urls import reverse
|
|
||||||
from mistune import HTMLRenderer, Markdown
|
|
||||||
|
|
||||||
if TYPE_CHECKING:
|
|
||||||
from mistune import InlineParser, InlineState
|
|
||||||
|
|
||||||
# match __text__, without linebreak in the text, nor backslash prepending an underscore
|
|
||||||
# Examples :
|
|
||||||
# - "__text__" : OK
|
|
||||||
# - "__te xt__" : OK
|
|
||||||
# - "__te_xt__" : nope (underscore in the middle)
|
|
||||||
# - "__te\_xt__" : Ok (the middle underscore is escaped)
|
|
||||||
# - "__te\nxt__" : nope (there is a linebreak in the text)
|
|
||||||
# - "\__text__" : nope (one of the underscores have a backslash prepended)
|
|
||||||
# - "\\__text__" : Ok (the backslash is ignored, because there is another backslash before)
|
|
||||||
UNDERLINED_RE = (
|
|
||||||
r"(?<!\\)(?:\\{2})*" # ignore if there is an odd number of backslashes before
|
|
||||||
r"_{2}" # two underscores
|
|
||||||
r"(?P<underlined>([^\\_]|\\.)+)" # the actual text
|
|
||||||
r"_{2}" # closing underscores
|
|
||||||
)
|
|
||||||
|
|
||||||
SITH_LINK_RE = (
|
|
||||||
r"\[(?P<page_name>[\w\s]+)\]" # [nom du lien]
|
|
||||||
r"\(page:\/\/" # (page://
|
|
||||||
r"(?P<page_slug>[a-zA-Z0-9][a-zA-Z0-9.-]*[a-zA-Z0-9])" # actual page name
|
|
||||||
r"\)" # )
|
|
||||||
)
|
|
||||||
|
|
||||||
CUSTOM_DIMENSIONS_IMAGE_RE = (
|
|
||||||
r"\[(?P<img_name>[\w\s]+)\]" # [nom du lien]
|
|
||||||
r"\(img:\/\/" # (img://
|
|
||||||
r"(?P<img_slug>[a-zA-Z0-9][a-zA-Z0-9.-]*[a-zA-Z0-9])" # actual page name
|
|
||||||
r"\)" # )
|
|
||||||
)
|
|
||||||
|
|
||||||
|
|
||||||
def parse_underline(_inline: InlineParser, m: re.Match, state: InlineState):
|
|
||||||
state.append_token({"type": "underline", "raw": m.group("underlined")})
|
|
||||||
return m.end()
|
|
||||||
|
|
||||||
|
|
||||||
def underline(md_instance: Markdown):
|
|
||||||
md_instance.inline.register(
|
|
||||||
"underline",
|
|
||||||
UNDERLINED_RE,
|
|
||||||
parse_underline,
|
|
||||||
before="emphasis",
|
|
||||||
)
|
|
||||||
md_instance.renderer.register("underline", lambda _, text: f"<u>{text}</u>")
|
|
||||||
|
|
||||||
|
|
||||||
def parse_sith_link(_inline: InlineParser, m: re.Match, state: InlineState):
|
|
||||||
page_name = m.group("page_name")
|
|
||||||
page_slug = m.group("page_slug")
|
|
||||||
state.append_token(
|
|
||||||
{
|
|
||||||
"type": "link",
|
|
||||||
"children": [{"type": "text", "raw": page_name}],
|
|
||||||
"attrs": {"url": reverse("core:page", kwargs={"page_name": page_slug})},
|
|
||||||
}
|
|
||||||
)
|
|
||||||
return m.end()
|
|
||||||
|
|
||||||
|
|
||||||
def sith_link(md_instance: Markdown):
|
|
||||||
md_instance.inline.register(
|
|
||||||
"sith_link",
|
|
||||||
SITH_LINK_RE,
|
|
||||||
parse_sith_link,
|
|
||||||
before="emphasis",
|
|
||||||
)
|
|
||||||
# no custom renderer here.
|
|
||||||
# we just add another parsing rule, but render it as if it was
|
|
||||||
# a regular markdown link
|
|
||||||
|
|
||||||
|
|
||||||
class SithRenderer(HTMLRenderer):
|
|
||||||
def image(self, text: str, url: str, title=None) -> str:
|
|
||||||
if "?" not in url:
|
|
||||||
return super().image(text, url, title)
|
|
||||||
|
|
||||||
new_url, params = url.rsplit("?", maxsplit=1)
|
|
||||||
m = re.match(r"^(?P<width>\d+(%|px)?)(x(?P<height>\d+(%|px)?))?$", params)
|
|
||||||
if not m:
|
|
||||||
return super().image(text, url, title)
|
|
||||||
|
|
||||||
width, height = m.group("width"), m.group("height")
|
|
||||||
if not width.endswith(("%", "px")):
|
|
||||||
width += "px"
|
|
||||||
style = f"width:{width};"
|
|
||||||
if height is not None:
|
|
||||||
if not height.endswith(("%", "px")):
|
|
||||||
height += "px"
|
|
||||||
style += f"height:{height};"
|
|
||||||
return super().image(text, new_url, title).replace("/>", f'style="{style}" />')
|
|
||||||
|
|
||||||
|
|
||||||
markdown = mistune.create_markdown(
|
|
||||||
renderer=SithRenderer(escape=True),
|
|
||||||
plugins=[
|
|
||||||
underline,
|
|
||||||
sith_link,
|
|
||||||
"strikethrough",
|
|
||||||
"footnotes",
|
|
||||||
"table",
|
|
||||||
"spoiler",
|
|
||||||
"subscript",
|
|
||||||
"superscript",
|
|
||||||
"url",
|
|
||||||
],
|
|
||||||
)
|
|
||||||
-1
@@ -55,7 +55,6 @@ declare interface NDEFRecordInit {
|
|||||||
// biome-ignore lint/style/useNamingConvention: this is the official API name
|
// biome-ignore lint/style/useNamingConvention: this is the official API name
|
||||||
declare type NDEFMessageSource = string | BufferSource | NDEFMessageInit;
|
declare type NDEFMessageSource = string | BufferSource | NDEFMessageInit;
|
||||||
|
|
||||||
// biome-ignore lint/correctness/noUnusedVariables: this is the official definition
|
|
||||||
interface Window {
|
interface Window {
|
||||||
// biome-ignore lint/style/useNamingConvention: this is the official API name
|
// biome-ignore lint/style/useNamingConvention: this is the official API name
|
||||||
NDEFReader: NDEFReader;
|
NDEFReader: NDEFReader;
|
||||||
|
|||||||
@@ -25,14 +25,13 @@
|
|||||||
import datetime
|
import datetime
|
||||||
|
|
||||||
import phonenumbers
|
import phonenumbers
|
||||||
|
from aemark import markdown as md
|
||||||
from django import template
|
from django import template
|
||||||
from django.forms import BoundField
|
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
|
||||||
|
|
||||||
from core.markdown import markdown as md
|
|
||||||
|
|
||||||
register = template.Library()
|
register = template.Library()
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
+9
-12
@@ -18,6 +18,7 @@ from smtplib import SMTPException
|
|||||||
|
|
||||||
import freezegun
|
import freezegun
|
||||||
import pytest
|
import pytest
|
||||||
|
from aemark import markdown
|
||||||
from bs4 import BeautifulSoup
|
from bs4 import BeautifulSoup
|
||||||
from django.contrib.auth.hashers import make_password
|
from django.contrib.auth.hashers import make_password
|
||||||
from django.contrib.auth.models import Permission
|
from django.contrib.auth.models import Permission
|
||||||
@@ -34,7 +35,6 @@ from pytest_django.asserts import assertInHTML, assertRedirects
|
|||||||
from antispam.models import ToxicDomain
|
from antispam.models import ToxicDomain
|
||||||
from club.models import Club
|
from club.models import Club
|
||||||
from core.baker_recipes import subscriber_user
|
from core.baker_recipes import subscriber_user
|
||||||
from core.markdown import markdown
|
|
||||||
from core.models import AnonymousUser, Group, Page, User, validate_promo
|
from core.models import AnonymousUser, Group, Page, User, validate_promo
|
||||||
from core.utils import get_last_promo, get_semester_code, get_start_of_semester
|
from core.utils import get_last_promo, get_semester_code, get_start_of_semester
|
||||||
from core.views import AllowFragment
|
from core.views import AllowFragment
|
||||||
@@ -200,31 +200,28 @@ class TestUserLogin:
|
|||||||
[
|
[
|
||||||
(
|
(
|
||||||
"[nom du lien](page://nomDeLaPage)",
|
"[nom du lien](page://nomDeLaPage)",
|
||||||
'<a href="/page/nomDeLaPage/">nom du lien</a>',
|
'<a href="/page/nomDeLaPage">nom du lien</a>',
|
||||||
),
|
),
|
||||||
("__texte__", "<u>texte</u>"),
|
("__texte__", "<u>texte</u>"),
|
||||||
("~~***__texte__***~~", "<del><em><strong><u>texte</u></strong></em></del>"),
|
("~~***__texte__***~~", "<del><em><strong><u>texte</u></strong></em></del>"),
|
||||||
(
|
(
|
||||||
'',
|
'',
|
||||||
'<img src="/img.png" alt="tst_alt" title="tst_title" style="width:50%;" />',
|
'<img src="/img.png" style="width:50%" alt="tst_alt" title="tst_title" />',
|
||||||
),
|
|
||||||
(
|
|
||||||
"[texte](page://tst-page)",
|
|
||||||
'<a href="/page/tst-page/">texte</a>',
|
|
||||||
),
|
),
|
||||||
|
("[texte](page://tst-page)", '<a href="/page/tst-page">texte</a>'),
|
||||||
(
|
(
|
||||||
"",
|
"",
|
||||||
'<img src="/img.png" alt="" style="width:50px;height:450px;" />',
|
'<img src="/img.png" style="width:50px;height:450px" alt="" />',
|
||||||
),
|
),
|
||||||
("", '<img src="/img.png" alt="" />'),
|
("", '<img src="/img.png" alt="" />'),
|
||||||
(
|
(
|
||||||
"",
|
"",
|
||||||
'<img src="/img.png" alt="" style="width:50%;height:120%;" />',
|
'<img src="/img.png" style="width:50%;height:120%" alt="" />',
|
||||||
),
|
),
|
||||||
("", '<img src="/img.png" alt="" style="width:50px;" />'),
|
("", '<img src="/img.png" style="width:50px" alt="" />'),
|
||||||
(
|
(
|
||||||
"",
|
"",
|
||||||
'<img src="/img.png" alt="" style="width:50px;height:120%;" />',
|
'<img src="/img.png" style="width:50px;height:120%" alt="" />',
|
||||||
),
|
),
|
||||||
# when the image dimension has a wrong format, don't touch the url
|
# when the image dimension has a wrong format, don't touch the url
|
||||||
("", '<img src="/img.png?50pxxxxxxxx" alt="" />'),
|
("", '<img src="/img.png?50pxxxxxxxx" alt="" />'),
|
||||||
@@ -350,7 +347,7 @@ http://git.an
|
|||||||
<p><a href="http://git.an">http://git.an</a></p>
|
<p><a href="http://git.an">http://git.an</a></p>
|
||||||
<h1>Swag</h1>
|
<h1>Swag</h1>
|
||||||
<p><guy>Bibou</guy></p>
|
<p><guy>Bibou</guy></p>
|
||||||
<p><script>alert('Guy');</script></p>
|
<script>alert('Guy');</script>
|
||||||
"""
|
"""
|
||||||
assertInHTML(expected, response.text)
|
assertInHTML(expected, response.text)
|
||||||
|
|
||||||
|
|||||||
@@ -2,6 +2,7 @@ from datetime import timedelta
|
|||||||
|
|
||||||
import freezegun
|
import freezegun
|
||||||
import pytest
|
import pytest
|
||||||
|
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
|
||||||
@@ -13,7 +14,6 @@ from pytest_django.asserts import assertHTMLEqual, assertRedirects
|
|||||||
|
|
||||||
from club.models import Club, Membership
|
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.markdown import markdown
|
|
||||||
from core.models import AnonymousUser, Page, PageRev, User
|
from core.models import AnonymousUser, Page, PageRev, User
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -200,7 +200,11 @@ class TestFilterInactive(TestCase):
|
|||||||
]
|
]
|
||||||
sale_recipe.make(customer=cls.users[3].customer, date=time_active)
|
sale_recipe.make(customer=cls.users[3].customer, date=time_active)
|
||||||
baker.make(
|
baker.make(
|
||||||
Refilling, customer=cls.users[4].customer, date=time_active, counter=counter
|
Refilling,
|
||||||
|
customer=cls.users[4].customer,
|
||||||
|
date=time_active,
|
||||||
|
counter=counter,
|
||||||
|
amount=1,
|
||||||
)
|
)
|
||||||
sale_recipe.make(customer=cls.users[5].customer, date=time_inactive)
|
sale_recipe.make(customer=cls.users[5].customer, date=time_inactive)
|
||||||
|
|
||||||
@@ -455,7 +459,9 @@ def test_user_preferences(client: Client):
|
|||||||
@pytest.mark.django_db
|
@pytest.mark.django_db
|
||||||
def test_user_stats(client: Client):
|
def test_user_stats(client: Client):
|
||||||
user = subscriber_user.make()
|
user = subscriber_user.make()
|
||||||
baker.make(Refilling, customer=user.customer, amount=99999)
|
baker.make(
|
||||||
|
Refilling, customer=user.customer, amount=settings.SITH_ACCOUNT_MAX_MONEY
|
||||||
|
)
|
||||||
bars = [b[0] for b in settings.SITH_COUNTER_BARS]
|
bars = [b[0] for b in settings.SITH_COUNTER_BARS]
|
||||||
baker.make(
|
baker.make(
|
||||||
Permanency,
|
Permanency,
|
||||||
|
|||||||
+50
-4
@@ -1,22 +1,68 @@
|
|||||||
from decimal import Decimal
|
from decimal import Decimal
|
||||||
|
|
||||||
from django.conf import settings
|
from django.conf import settings
|
||||||
|
from django.core import checks
|
||||||
|
from django.core.validators import MaxValueValidator, MinValueValidator
|
||||||
from django.db import models
|
from django.db import models
|
||||||
|
from django.utils.functional import cached_property
|
||||||
|
|
||||||
|
|
||||||
class CurrencyField(models.DecimalField):
|
class CurrencyField(models.DecimalField):
|
||||||
"""Custom database field used for currency."""
|
"""Custom database field used for currency."""
|
||||||
|
|
||||||
def __init__(self, *args, **kwargs):
|
def __init__(
|
||||||
kwargs["max_digits"] = 12
|
self, verbose_name=None, name=None, min_value=None, max_value=None, **kwargs
|
||||||
kwargs["decimal_places"] = 2
|
):
|
||||||
super().__init__(*args, **kwargs)
|
kwargs.update({"max_digits": 12, "decimal_places": 2})
|
||||||
|
self.min_value = min_value
|
||||||
|
self.max_value = max_value
|
||||||
|
super().__init__(verbose_name, name, **kwargs)
|
||||||
|
|
||||||
def to_python(self, value):
|
def to_python(self, value):
|
||||||
if value is None:
|
if value is None:
|
||||||
return None
|
return None
|
||||||
return super().to_python(value).quantize(Decimal("0.01"))
|
return super().to_python(value).quantize(Decimal("0.01"))
|
||||||
|
|
||||||
|
@cached_property
|
||||||
|
def validators(self):
|
||||||
|
res = []
|
||||||
|
if self.max_value:
|
||||||
|
res.append(MaxValueValidator(self.max_value))
|
||||||
|
if self.min_value:
|
||||||
|
res.append(MinValueValidator(self.min_value))
|
||||||
|
return [*super().validators, *res]
|
||||||
|
|
||||||
|
def check(self, **kwargs): # pragma: no cover
|
||||||
|
# this is executed during runserver, but won't run in prod
|
||||||
|
errors = super().check(**kwargs)
|
||||||
|
for name, val in ("min_value", self.min_value), ("max_value", self.max_value):
|
||||||
|
if not val:
|
||||||
|
continue
|
||||||
|
try:
|
||||||
|
float(val)
|
||||||
|
except ValueError:
|
||||||
|
errors.append(
|
||||||
|
checks.Error(
|
||||||
|
f"CurrencyField.{name} must be a valid float",
|
||||||
|
obj=self,
|
||||||
|
id="sith.E001",
|
||||||
|
)
|
||||||
|
)
|
||||||
|
return errors
|
||||||
|
|
||||||
|
def formfield(self, **kwargs):
|
||||||
|
return super().formfield(
|
||||||
|
**{"min_value": self.min_value, "max_value": self.max_value, **kwargs}
|
||||||
|
)
|
||||||
|
|
||||||
|
def deconstruct(self):
|
||||||
|
name, path, args, kwargs = super().deconstruct()
|
||||||
|
if self.min_value is not None:
|
||||||
|
kwargs["min_value"] = self.min_value
|
||||||
|
if self.max_value is not None:
|
||||||
|
kwargs["max_value"] = self.max_value
|
||||||
|
return name, path, args, kwargs
|
||||||
|
|
||||||
|
|
||||||
if settings.TESTING:
|
if settings.TESTING:
|
||||||
from model_bakery import baker
|
from model_bakery import baker
|
||||||
|
|||||||
+61
-29
@@ -3,13 +3,16 @@ 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 ClassVar
|
||||||
|
|
||||||
from dateutil.relativedelta import relativedelta
|
from dateutil.relativedelta import relativedelta
|
||||||
from django import forms
|
from django import forms
|
||||||
|
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.http import HttpRequest
|
||||||
|
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 _
|
||||||
from django_celery_beat.models import ClockedSchedule
|
from django_celery_beat.models import ClockedSchedule
|
||||||
@@ -39,6 +42,7 @@ from counter.models import (
|
|||||||
Customer,
|
Customer,
|
||||||
Eticket,
|
Eticket,
|
||||||
InvoiceCall,
|
InvoiceCall,
|
||||||
|
Permanency,
|
||||||
Price,
|
Price,
|
||||||
Product,
|
Product,
|
||||||
ProductFormula,
|
ProductFormula,
|
||||||
@@ -151,12 +155,13 @@ class CounterLoginForm(LoginForm):
|
|||||||
raise ValidationError(
|
raise ValidationError(
|
||||||
message=_("You are not a barman of this counter."), code="not_barman"
|
message=_("You are not a barman of this counter."), code="not_barman"
|
||||||
)
|
)
|
||||||
if user in self.request.barmen:
|
if Permanency.objects.filter(end=None, user=user).exists():
|
||||||
message = (
|
if user in self.request.barmen:
|
||||||
_("You are already logged in this counter.")
|
message = _("You are already logged in this counter.")
|
||||||
if user in self.counter.barmen_list
|
elif user in self.counter.barmen_list:
|
||||||
else _("You are already logged in another counter.")
|
message = _("You are already logged in another counter.")
|
||||||
)
|
else:
|
||||||
|
message = _("You are already logged on another device")
|
||||||
raise ValidationError(message=message, code="already_logged_in")
|
raise ValidationError(message=message, code="already_logged_in")
|
||||||
|
|
||||||
|
|
||||||
@@ -168,18 +173,19 @@ class RefillForm(forms.ModelForm):
|
|||||||
|
|
||||||
error_css_class = "error"
|
error_css_class = "error"
|
||||||
required_css_class = "required"
|
required_css_class = "required"
|
||||||
amount = forms.FloatField(
|
|
||||||
min_value=0, widget=forms.NumberInput(attrs={"class": "focus"})
|
|
||||||
)
|
|
||||||
|
|
||||||
class Meta:
|
class Meta:
|
||||||
model = Refilling
|
model = Refilling
|
||||||
fields = ["amount", "payment_method"]
|
fields = ["amount", "payment_method"]
|
||||||
widgets = {"payment_method": forms.RadioSelect}
|
widgets = {"payment_method": forms.RadioSelect}
|
||||||
|
|
||||||
def __init__(self, *args, **kwargs):
|
def __init__(
|
||||||
|
self, *args, counter: Counter, operator: User, customer: Customer, **kwargs
|
||||||
|
):
|
||||||
super().__init__(*args, **kwargs)
|
super().__init__(*args, **kwargs)
|
||||||
|
max_value = settings.SITH_ACCOUNT_MAX_MONEY - customer.amount
|
||||||
|
# server-side max_value validation is done by Refilling.clean
|
||||||
|
self.fields["amount"].widget.attrs["max"] = max_value
|
||||||
self.fields["payment_method"].choices = (
|
self.fields["payment_method"].choices = (
|
||||||
method
|
method
|
||||||
for method in self.fields["payment_method"].choices
|
for method in self.fields["payment_method"].choices
|
||||||
@@ -187,6 +193,9 @@ class RefillForm(forms.ModelForm):
|
|||||||
)
|
)
|
||||||
if self.fields["payment_method"].initial not in self.allowed_refilling_methods:
|
if self.fields["payment_method"].initial not in self.allowed_refilling_methods:
|
||||||
self.fields["payment_method"].initial = self.allowed_refilling_methods[0]
|
self.fields["payment_method"].initial = self.allowed_refilling_methods[0]
|
||||||
|
self.instance.counter = counter
|
||||||
|
self.instance.operator = operator
|
||||||
|
self.instance.customer = customer
|
||||||
|
|
||||||
|
|
||||||
class CounterEditForm(forms.ModelForm):
|
class CounterEditForm(forms.ModelForm):
|
||||||
@@ -560,16 +569,7 @@ class BasketItemForm(forms.Form):
|
|||||||
quantity = forms.IntegerField(min_value=1, required=True)
|
quantity = forms.IntegerField(min_value=1, required=True)
|
||||||
price_id = forms.IntegerField(min_value=0, required=True)
|
price_id = forms.IntegerField(min_value=0, required=True)
|
||||||
|
|
||||||
def __init__(
|
def __init__(self, allowed_prices: dict[int, Price], *args, **kwargs):
|
||||||
self,
|
|
||||||
customer: Customer,
|
|
||||||
counter: Counter,
|
|
||||||
allowed_prices: dict[int, Price],
|
|
||||||
*args,
|
|
||||||
**kwargs,
|
|
||||||
):
|
|
||||||
self.customer = customer # Used by formset
|
|
||||||
self.counter = counter # Used by formset
|
|
||||||
self.allowed_prices = allowed_prices
|
self.allowed_prices = allowed_prices
|
||||||
super().__init__(*args, **kwargs)
|
super().__init__(*args, **kwargs)
|
||||||
|
|
||||||
@@ -604,6 +604,15 @@ class BasketItemForm(forms.Form):
|
|||||||
|
|
||||||
|
|
||||||
class BaseBasketForm(forms.BaseFormSet):
|
class BaseBasketForm(forms.BaseFormSet):
|
||||||
|
# Minimum amount of money there must be on the account after the transaction
|
||||||
|
# If None, the min balance check is skipped
|
||||||
|
min_result_balance: ClassVar[int | None] = 0
|
||||||
|
|
||||||
|
def __init__(self, *args, customer: Customer, counter: Counter, **kwargs):
|
||||||
|
super().__init__(*args, **kwargs)
|
||||||
|
self.customer = customer
|
||||||
|
self.counter = counter
|
||||||
|
|
||||||
def clean(self):
|
def clean(self):
|
||||||
self.forms = [form for form in self.forms if form.cleaned_data != {}]
|
self.forms = [form for form in self.forms if form.cleaned_data != {}]
|
||||||
|
|
||||||
@@ -612,8 +621,8 @@ class BaseBasketForm(forms.BaseFormSet):
|
|||||||
|
|
||||||
self._check_forms_have_errors()
|
self._check_forms_have_errors()
|
||||||
self._check_product_are_unique()
|
self._check_product_are_unique()
|
||||||
self._check_recorded_products(self[0].customer)
|
self._check_recorded_products()
|
||||||
self._check_enough_money(self[0].counter, self[0].customer)
|
self._check_account_balance()
|
||||||
|
|
||||||
def _check_forms_have_errors(self):
|
def _check_forms_have_errors(self):
|
||||||
if any(len(form.errors) > 0 for form in self):
|
if any(len(form.errors) > 0 for form in self):
|
||||||
@@ -624,12 +633,35 @@ class BaseBasketForm(forms.BaseFormSet):
|
|||||||
if len(price_ids) != len(self.forms):
|
if len(price_ids) != len(self.forms):
|
||||||
raise forms.ValidationError(_("Duplicated product entries."))
|
raise forms.ValidationError(_("Duplicated product entries."))
|
||||||
|
|
||||||
def _check_enough_money(self, counter: Counter, customer: Customer):
|
@cached_property
|
||||||
self.total_price = sum([data["total_price"] for data in self.cleaned_data])
|
def total_price(self):
|
||||||
if self.total_price > customer.amount:
|
refill = settings.SITH_COUNTER_PRODUCTTYPE_REFILLING
|
||||||
raise forms.ValidationError(_("Not enough money"))
|
total_other = sum(
|
||||||
|
form.cleaned_data["total_price"]
|
||||||
|
for form in self.forms
|
||||||
|
if form.price.product.product_type_id != refill
|
||||||
|
)
|
||||||
|
total_refill = sum(
|
||||||
|
form.cleaned_data["total_price"]
|
||||||
|
for form in self.forms
|
||||||
|
if form.price.product.product_type_id == refill
|
||||||
|
)
|
||||||
|
return total_other - total_refill
|
||||||
|
|
||||||
def _check_recorded_products(self, customer: Customer):
|
def _check_account_balance(self):
|
||||||
|
result_balance = self.customer.amount - self.total_price
|
||||||
|
if (
|
||||||
|
self.min_result_balance is not None
|
||||||
|
and self.min_result_balance > result_balance
|
||||||
|
):
|
||||||
|
raise forms.ValidationError(_("Not enough money"))
|
||||||
|
if result_balance > settings.SITH_ACCOUNT_MAX_MONEY:
|
||||||
|
raise ValidationError(
|
||||||
|
_("There cannot be more than %(money)d€ on an AE account")
|
||||||
|
% {"money": settings.SITH_ACCOUNT_MAX_MONEY}
|
||||||
|
)
|
||||||
|
|
||||||
|
def _check_recorded_products(self):
|
||||||
"""Check for, among other things, ecocups and pitchers"""
|
"""Check for, among other things, ecocups and pitchers"""
|
||||||
items = defaultdict(int)
|
items = defaultdict(int)
|
||||||
for form in self.forms:
|
for form in self.forms:
|
||||||
@@ -638,7 +670,7 @@ class BaseBasketForm(forms.BaseFormSet):
|
|||||||
returnables = list(
|
returnables = list(
|
||||||
ReturnableProduct.objects.filter(
|
ReturnableProduct.objects.filter(
|
||||||
Q(product_id__in=ids) | Q(returned_product_id__in=ids)
|
Q(product_id__in=ids) | Q(returned_product_id__in=ids)
|
||||||
).annotate_balance_for(customer)
|
).annotate_balance_for(self.customer)
|
||||||
)
|
)
|
||||||
limit_reached = []
|
limit_reached = []
|
||||||
for returnable in returnables:
|
for returnable in returnables:
|
||||||
|
|||||||
+21
-19
@@ -1,8 +1,7 @@
|
|||||||
from typing import TYPE_CHECKING, Callable
|
from typing import TYPE_CHECKING, Callable
|
||||||
|
|
||||||
from django.db.models import Exists, OuterRef
|
|
||||||
from django.http import HttpRequest, HttpResponse
|
from django.http import HttpRequest, HttpResponse
|
||||||
from django.utils.functional import SimpleLazyObject, empty
|
from django.utils.functional import SimpleLazyObject
|
||||||
|
|
||||||
from core.models import User
|
from core.models import User
|
||||||
from counter.models import Permanency
|
from counter.models import Permanency
|
||||||
@@ -11,20 +10,31 @@ if TYPE_CHECKING:
|
|||||||
from django.contrib.sessions.backends.base import SessionBase
|
from django.contrib.sessions.backends.base import SessionBase
|
||||||
|
|
||||||
|
|
||||||
SESSION_BARMEN_KEY = "barmen_ids"
|
SESSION_PERMANENCES_KEY = "permanence_ids"
|
||||||
|
|
||||||
|
|
||||||
def get_cached_barmen(request: HttpRequest) -> set[User]:
|
def get_cached_barmen(request: HttpRequest) -> set[User]:
|
||||||
if not hasattr(request, "_cached_barmen"):
|
if not hasattr(request, "_cached_barmen"):
|
||||||
session: SessionBase = request.session
|
session: SessionBase = request.session
|
||||||
barmen_ids = session.get(SESSION_BARMEN_KEY, [])
|
|
||||||
if barmen_ids:
|
if session_ids := session.get(SESSION_PERMANENCES_KEY, None):
|
||||||
request._cached_barmen = set(
|
# Get ongoing permanences which id is in session.
|
||||||
User.objects.filter(
|
# Note : we store permanence ids rather than user id to be sure
|
||||||
Exists(Permanency.objects.filter(user=OuterRef("pk"), end=None)),
|
# not to wrongfully mark someone as logged here,
|
||||||
id__in=barmen_ids,
|
# even if it logged out then logged in elsewhere.
|
||||||
)
|
permanences = (
|
||||||
|
Permanency.objects.filter(end=None, id__in=session_ids)
|
||||||
|
.order_by("id")
|
||||||
|
.select_related("user")
|
||||||
)
|
)
|
||||||
|
|
||||||
|
# if the list of permanences occurring on this device has changed
|
||||||
|
# since the last page load, change the ids stored in session
|
||||||
|
real_ids = [p.id for p in permanences]
|
||||||
|
if real_ids != session_ids:
|
||||||
|
session[SESSION_PERMANENCES_KEY] = real_ids
|
||||||
|
|
||||||
|
request._cached_barmen = {p.user for p in permanences}
|
||||||
else:
|
else:
|
||||||
request._cached_barmen = set()
|
request._cached_barmen = set()
|
||||||
|
|
||||||
@@ -53,12 +63,4 @@ class BarmenMiddleware:
|
|||||||
def __call__(self, request: HttpRequest):
|
def __call__(self, request: HttpRequest):
|
||||||
request.barmen = SimpleLazyObject(lambda: get_cached_barmen(request))
|
request.barmen = SimpleLazyObject(lambda: get_cached_barmen(request))
|
||||||
|
|
||||||
response = self.get_response(request)
|
return self.get_response(request)
|
||||||
|
|
||||||
if request.barmen._wrapped is not empty and {
|
|
||||||
b.id for b in request.barmen
|
|
||||||
} != set(request.session.get(SESSION_BARMEN_KEY, [])):
|
|
||||||
# update the session data only if `session.barmen`
|
|
||||||
# has been accessed and modified.
|
|
||||||
request.session[SESSION_BARMEN_KEY] = [b.id for b in request.barmen]
|
|
||||||
return response
|
|
||||||
|
|||||||
@@ -0,0 +1,30 @@
|
|||||||
|
# Generated by Django 5.2.15 on 2026-06-07 12:08
|
||||||
|
|
||||||
|
from django.db import migrations
|
||||||
|
|
||||||
|
import counter.fields
|
||||||
|
|
||||||
|
|
||||||
|
class Migration(migrations.Migration):
|
||||||
|
dependencies = [("counter", "0041_alter_billinginfo_country_and_more")]
|
||||||
|
|
||||||
|
operations = [
|
||||||
|
migrations.AlterField(
|
||||||
|
model_name="customer",
|
||||||
|
name="amount",
|
||||||
|
field=counter.fields.CurrencyField(
|
||||||
|
decimal_places=2,
|
||||||
|
default=0,
|
||||||
|
max_digits=12,
|
||||||
|
max_value=250,
|
||||||
|
verbose_name="amount",
|
||||||
|
),
|
||||||
|
),
|
||||||
|
migrations.AlterField(
|
||||||
|
model_name="refilling",
|
||||||
|
name="amount",
|
||||||
|
field=counter.fields.CurrencyField(
|
||||||
|
decimal_places=2, max_digits=12, min_value=0.01, verbose_name="amount"
|
||||||
|
),
|
||||||
|
),
|
||||||
|
]
|
||||||
+20
-8
@@ -28,7 +28,7 @@ from dict2xml import dict2xml
|
|||||||
from django.conf import settings
|
from django.conf import settings
|
||||||
from django.core.validators import MinLengthValidator
|
from django.core.validators import MinLengthValidator
|
||||||
from django.db import models
|
from django.db import models
|
||||||
from django.db.models import Exists, F, OuterRef, Q, QuerySet, Subquery, Sum, Value
|
from django.db.models import Exists, F, Max, OuterRef, Q, QuerySet, Subquery, Sum, Value
|
||||||
from django.db.models.functions import Coalesce, Concat, Length
|
from django.db.models.functions import Coalesce, Concat, Length
|
||||||
from django.forms import ValidationError
|
from django.forms import ValidationError
|
||||||
from django.urls import reverse
|
from django.urls import reverse
|
||||||
@@ -99,7 +99,9 @@ class Customer(models.Model):
|
|||||||
|
|
||||||
user = models.OneToOneField(User, primary_key=True, on_delete=models.CASCADE)
|
user = models.OneToOneField(User, primary_key=True, on_delete=models.CASCADE)
|
||||||
account_id = models.CharField(_("account id"), max_length=10, unique=True)
|
account_id = models.CharField(_("account id"), max_length=10, unique=True)
|
||||||
amount = CurrencyField(_("amount"), default=0)
|
amount: CurrencyField = CurrencyField(
|
||||||
|
_("amount"), max_value=settings.SITH_ACCOUNT_MAX_MONEY, default=0
|
||||||
|
)
|
||||||
|
|
||||||
objects = CustomerQuerySet.as_manager()
|
objects = CustomerQuerySet.as_manager()
|
||||||
|
|
||||||
@@ -156,13 +158,15 @@ class Customer(models.Model):
|
|||||||
unique_fields=["customer", "returnable"],
|
unique_fields=["customer", "returnable"],
|
||||||
)
|
)
|
||||||
|
|
||||||
@property
|
@cached_property
|
||||||
def can_buy(self) -> bool:
|
def can_buy(self) -> bool:
|
||||||
"""Check if whether this customer has the right to purchase any item."""
|
"""Check if whether this customer has the right to purchase any item."""
|
||||||
subscription = self.user.subscriptions.order_by("subscription_end").last()
|
subscription_end = self.user.subscriptions.aggregate(
|
||||||
if subscription is None:
|
res=Max("subscription_end")
|
||||||
|
).get("res")
|
||||||
|
if subscription_end is None:
|
||||||
return False
|
return False
|
||||||
return (date.today() - subscription.subscription_end) < timedelta(days=90)
|
return (date.today() - subscription_end) < timedelta(days=90)
|
||||||
|
|
||||||
@classmethod
|
@classmethod
|
||||||
def get_or_create(cls, user: User) -> tuple[Customer, bool]:
|
def get_or_create(cls, user: User) -> tuple[Customer, bool]:
|
||||||
@@ -823,7 +827,7 @@ class Refilling(models.Model):
|
|||||||
counter = models.ForeignKey(
|
counter = models.ForeignKey(
|
||||||
Counter, related_name="refillings", blank=False, on_delete=models.CASCADE
|
Counter, related_name="refillings", blank=False, on_delete=models.CASCADE
|
||||||
)
|
)
|
||||||
amount = CurrencyField(_("amount"))
|
amount: CurrencyField = CurrencyField(_("amount"), min_value=0.01)
|
||||||
operator = models.ForeignKey(
|
operator = models.ForeignKey(
|
||||||
User,
|
User,
|
||||||
related_name="refillings_as_operator",
|
related_name="refillings_as_operator",
|
||||||
@@ -877,6 +881,14 @@ class Refilling(models.Model):
|
|||||||
return False
|
return False
|
||||||
return user.is_owner(self.counter) and self.payment_method != "CARD"
|
return user.is_owner(self.counter) and self.payment_method != "CARD"
|
||||||
|
|
||||||
|
def clean(self):
|
||||||
|
super().clean()
|
||||||
|
if (self.amount + self.customer.amount) > settings.SITH_ACCOUNT_MAX_MONEY:
|
||||||
|
raise ValidationError(
|
||||||
|
_("There cannot be more than %(money)d€ on an AE account")
|
||||||
|
% {"money": settings.SITH_ACCOUNT_MAX_MONEY}
|
||||||
|
)
|
||||||
|
|
||||||
def delete(self, *args, **kwargs):
|
def delete(self, *args, **kwargs):
|
||||||
self.customer.amount -= self.amount
|
self.customer.amount -= self.amount
|
||||||
self.customer.save()
|
self.customer.save()
|
||||||
@@ -1105,7 +1117,7 @@ class Permanency(models.Model):
|
|||||||
on_delete=models.CASCADE,
|
on_delete=models.CASCADE,
|
||||||
)
|
)
|
||||||
start = models.DateTimeField(_("start date"))
|
start = models.DateTimeField(_("start date"))
|
||||||
end = models.DateTimeField(_("end date"), null=True, db_index=True)
|
end = models.DateTimeField(_("end date"), null=True, blank=True, db_index=True)
|
||||||
activity = models.DateTimeField(_("last activity date"), auto_now=True)
|
activity = models.DateTimeField(_("last activity date"), auto_now=True)
|
||||||
|
|
||||||
class Meta:
|
class Meta:
|
||||||
|
|||||||
@@ -6,7 +6,7 @@ const productParsingRegex = /^(\d+x)?(.*)/i;
|
|||||||
const codeParsingRegex = / \((\w+)\)$/;
|
const codeParsingRegex = / \((\w+)\)$/;
|
||||||
|
|
||||||
function parseProduct(query: string): [number, string] {
|
function parseProduct(query: string): [number, string] {
|
||||||
const parsed = productParsingRegex.exec(query);
|
const parsed = productParsingRegex.exec(query) as RegExpExecArray;
|
||||||
return [Number.parseInt(parsed[1] || "1", 10), parsed[2]];
|
return [Number.parseInt(parsed[1] || "1", 10), parsed[2]];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -3,7 +3,6 @@ import { BasketItem } from "#counter:counter/basket";
|
|||||||
import type {
|
import type {
|
||||||
CounterConfig,
|
CounterConfig,
|
||||||
CounterItem,
|
CounterItem,
|
||||||
ErrorMessage,
|
|
||||||
ProductFormula,
|
ProductFormula,
|
||||||
} from "#counter:counter/types";
|
} from "#counter:counter/types";
|
||||||
import type { CounterProductSelect } from "./components/counter-product-select-index";
|
import type { CounterProductSelect } from "./components/counter-product-select-index";
|
||||||
@@ -24,7 +23,7 @@ document.addEventListener("alpine:init", () => {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
this.codeField = this.$refs.codeField;
|
this.codeField = this.$refs.codeField as CounterProductSelect;
|
||||||
this.codeField.widget.hook("after", "onOptionSelect", () => {
|
this.codeField.widget.hook("after", "onOptionSelect", () => {
|
||||||
this.handleCode();
|
this.handleCode();
|
||||||
});
|
});
|
||||||
@@ -34,14 +33,14 @@ document.addEventListener("alpine:init", () => {
|
|||||||
// of a formset so we dynamically apply it here
|
// of a formset so we dynamically apply it here
|
||||||
this.$refs.basketManagementForm
|
this.$refs.basketManagementForm
|
||||||
.querySelector("#id_form-TOTAL_FORMS")
|
.querySelector("#id_form-TOTAL_FORMS")
|
||||||
.setAttribute(":value", "getBasketSize()");
|
?.setAttribute(":value", "getBasketSize()");
|
||||||
},
|
},
|
||||||
|
|
||||||
removeFromBasket(id: string) {
|
removeFromBasket(id: string) {
|
||||||
delete this.basket[id];
|
delete this.basket[id];
|
||||||
},
|
},
|
||||||
|
|
||||||
addToBasket(id: string, quantity: number): ErrorMessage {
|
addToBasket(id: string, quantity: number) {
|
||||||
const item: BasketItem =
|
const item: BasketItem =
|
||||||
this.basket[id] || new BasketItem(config.products[id], 0);
|
this.basket[id] || new BasketItem(config.products[id], 0);
|
||||||
|
|
||||||
@@ -50,7 +49,7 @@ document.addEventListener("alpine:init", () => {
|
|||||||
|
|
||||||
if (item.quantity <= 0) {
|
if (item.quantity <= 0) {
|
||||||
delete this.basket[id];
|
delete this.basket[id];
|
||||||
return "";
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
this.basket[id] = item;
|
this.basket[id] = item;
|
||||||
@@ -72,7 +71,7 @@ document.addEventListener("alpine:init", () => {
|
|||||||
const products = new Set(
|
const products = new Set(
|
||||||
Object.values(this.basket).map((item: BasketItem) => item.product.productId),
|
Object.values(this.basket).map((item: BasketItem) => item.product.productId),
|
||||||
);
|
);
|
||||||
const formula: ProductFormula = config.formulas.find((f: ProductFormula) => {
|
const formula = config.formulas.find((f: ProductFormula) => {
|
||||||
return f.products.every((p: number) => products.has(p));
|
return f.products.every((p: number) => products.has(p));
|
||||||
});
|
});
|
||||||
if (formula === undefined) {
|
if (formula === undefined) {
|
||||||
@@ -80,9 +79,13 @@ document.addEventListener("alpine:init", () => {
|
|||||||
}
|
}
|
||||||
// Now that the formula is found, remove the items composing it from the basket
|
// Now that the formula is found, remove the items composing it from the basket
|
||||||
for (const product of formula.products) {
|
for (const product of formula.products) {
|
||||||
const key = Object.entries(this.basket).find(
|
const item = Object.entries(this.basket).find(
|
||||||
([_, i]: [string, BasketItem]) => i.product.productId === product,
|
([_, i]: [string, BasketItem]) => i.product.productId === product,
|
||||||
)[0];
|
);
|
||||||
|
if (item === undefined) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
const key = item[0];
|
||||||
this.basket[key].quantity -= 1;
|
this.basket[key].quantity -= 1;
|
||||||
if (this.basket[key].quantity <= 0) {
|
if (this.basket[key].quantity <= 0) {
|
||||||
this.removeFromBasket(key);
|
this.removeFromBasket(key);
|
||||||
@@ -92,7 +95,7 @@ document.addEventListener("alpine:init", () => {
|
|||||||
const result = Object.values(config.products)
|
const result = Object.values(config.products)
|
||||||
.filter((item: CounterItem) => item.productId === formula.result)
|
.filter((item: CounterItem) => item.productId === formula.result)
|
||||||
.reduce((acc, curr) => (acc.price.amount < curr.price.amount ? acc : curr));
|
.reduce((acc, curr) => (acc.price.amount < curr.price.amount ? acc : curr));
|
||||||
this.addToBasket(result.price.id, 1);
|
this.addToBasket(result.price.id.toString(), 1);
|
||||||
this.alertMessage.display(
|
this.alertMessage.display(
|
||||||
interpolate(
|
interpolate(
|
||||||
gettext("Formula %(formula)s applied"),
|
gettext("Formula %(formula)s applied"),
|
||||||
@@ -119,14 +122,18 @@ document.addEventListener("alpine:init", () => {
|
|||||||
},
|
},
|
||||||
|
|
||||||
onRefillingSuccess(event: CustomEvent) {
|
onRefillingSuccess(event: CustomEvent) {
|
||||||
if (event.type !== "htmx:after-request" || event.detail.failed) {
|
if (
|
||||||
|
event.type !== "htmx:after-swap" ||
|
||||||
|
event.detail.failed ||
|
||||||
|
event.detail.elt.querySelector(".errorlist")
|
||||||
|
) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
this.customerBalance += Number.parseFloat(
|
this.customerBalance += Number.parseFloat(
|
||||||
(event.detail.target.querySelector("#id_amount") as HTMLInputElement).value,
|
(event.detail.target.querySelector("#id_amount") as HTMLInputElement).value,
|
||||||
);
|
);
|
||||||
document.getElementById("selling-accordion").setAttribute("open", "");
|
document.getElementById("selling-accordion")?.setAttribute("open", "");
|
||||||
this.codeField.widget.focus();
|
this.codeField?.widget.focus();
|
||||||
},
|
},
|
||||||
|
|
||||||
finish() {
|
finish() {
|
||||||
@@ -136,7 +143,7 @@ document.addEventListener("alpine:init", () => {
|
|||||||
});
|
});
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
this.$refs.basketForm.submit();
|
(this.$refs.basketForm as HTMLFormElement).submit();
|
||||||
},
|
},
|
||||||
|
|
||||||
cancel() {
|
cancel() {
|
||||||
@@ -144,6 +151,8 @@ document.addEventListener("alpine:init", () => {
|
|||||||
},
|
},
|
||||||
|
|
||||||
handleCode() {
|
handleCode() {
|
||||||
|
if (!this.codeField) throw Error("Unexpected null codeField.");
|
||||||
|
|
||||||
const [quantity, code] = this.codeField.getSelectedProduct() as [number, string];
|
const [quantity, code] = this.codeField.getSelectedProduct() as [number, string];
|
||||||
|
|
||||||
if (this.codeField.getOperationCodes().includes(code.toUpperCase())) {
|
if (this.codeField.getOperationCodes().includes(code.toUpperCase())) {
|
||||||
|
|||||||
@@ -176,13 +176,17 @@
|
|||||||
</form>
|
</form>
|
||||||
</div>
|
</div>
|
||||||
</details>
|
</details>
|
||||||
<details class="accordion" name="selling">
|
<details
|
||||||
|
class="accordion"
|
||||||
|
name="selling"
|
||||||
|
@toggle="if ($event.newState === 'open') $el.querySelector('input[type=number]')?.focus()"
|
||||||
|
>
|
||||||
<summary>{% trans %}Refilling{% endtrans %}</summary>
|
<summary>{% trans %}Refilling{% endtrans %}</summary>
|
||||||
{% if object.type == "BAR" %}
|
{% if object.type == "BAR" %}
|
||||||
{% if refilling_fragment %}
|
{% if refilling_fragment %}
|
||||||
<div
|
<div
|
||||||
class="accordion-content"
|
class="accordion-content"
|
||||||
@htmx:after-request="onRefillingSuccess"
|
@htmx:after-swap="onRefillingSuccess"
|
||||||
>
|
>
|
||||||
{{ refilling_fragment }}
|
{{ refilling_fragment }}
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
@@ -144,6 +144,8 @@ class TestRefilling(TestFullClickBase):
|
|||||||
assert self.updated_amount(self.customer) == 0
|
assert self.updated_amount(self.customer) == 0
|
||||||
|
|
||||||
def test_refilling_no_refer_fail(self):
|
def test_refilling_no_refer_fail(self):
|
||||||
|
"""Check that the refill fails is the HTTP_REFERER header is missing"""
|
||||||
|
|
||||||
def refill():
|
def refill():
|
||||||
return self.client.post(
|
return self.client.post(
|
||||||
reverse(
|
reverse(
|
||||||
@@ -157,13 +159,13 @@ class TestRefilling(TestFullClickBase):
|
|||||||
)
|
)
|
||||||
|
|
||||||
self.client.force_login(self.club_admin)
|
self.client.force_login(self.club_admin)
|
||||||
assert refill()
|
assert refill().status_code == 403
|
||||||
|
|
||||||
self.client.force_login(self.root)
|
self.client.force_login(self.root)
|
||||||
assert refill()
|
assert refill().status_code == 403
|
||||||
|
|
||||||
self.client.force_login(self.subscriber)
|
self.client.force_login(self.subscriber)
|
||||||
assert refill()
|
assert refill().status_code == 403
|
||||||
|
|
||||||
assert self.updated_amount(self.customer) == 0
|
assert self.updated_amount(self.customer) == 0
|
||||||
|
|
||||||
@@ -199,6 +201,17 @@ class TestRefilling(TestFullClickBase):
|
|||||||
== 404
|
== 404
|
||||||
)
|
)
|
||||||
|
|
||||||
|
def test_refilling_above_limit_fails(self):
|
||||||
|
"""Test that it's forbidden to refill a customer above the limit."""
|
||||||
|
self.login_in_bar()
|
||||||
|
limit = settings.SITH_ACCOUNT_MAX_MONEY
|
||||||
|
# create a refilling to check that current balance is taken into account
|
||||||
|
baker.make(Refilling, customer=self.customer.customer, amount=limit // 2)
|
||||||
|
response = self.refill_user(self.customer, self.counter, (limit // 2) + 1)
|
||||||
|
assert response.status_code == 200 # no redirect = failure
|
||||||
|
self.customer.customer.refresh_from_db()
|
||||||
|
assert self.updated_amount(self.customer) == limit // 2
|
||||||
|
|
||||||
def test_refilling_counter_success(self):
|
def test_refilling_counter_success(self):
|
||||||
self.login_in_bar()
|
self.login_in_bar()
|
||||||
|
|
||||||
@@ -522,6 +535,19 @@ class TestCounterClick(TestFullClickBase):
|
|||||||
|
|
||||||
assert self.updated_amount(self.customer) == Decimal(10)
|
assert self.updated_amount(self.customer) == Decimal(10)
|
||||||
|
|
||||||
|
def test_unrecord_above_limit_fails(self):
|
||||||
|
"""Test that it's forbidden to give back a recorded product
|
||||||
|
if it puts the account balance above the limit.
|
||||||
|
"""
|
||||||
|
self.login_in_bar()
|
||||||
|
limit = settings.SITH_ACCOUNT_MAX_MONEY
|
||||||
|
# put the account balance just at the limit
|
||||||
|
baker.make(Refilling, customer=self.customer.customer, amount=limit)
|
||||||
|
response = self.submit_basket(self.customer, [BasketItem(self.dcons.id, 1)])
|
||||||
|
assert response.status_code == 200 # no redirect = failure
|
||||||
|
self.customer.customer.refresh_from_db()
|
||||||
|
assert self.updated_amount(self.customer) == limit
|
||||||
|
|
||||||
def test_annotate_has_barman_queryset(self):
|
def test_annotate_has_barman_queryset(self):
|
||||||
"""Test if the custom queryset method `annotate_has_barman` works as intended."""
|
"""Test if the custom queryset method `annotate_has_barman` works as intended."""
|
||||||
counters = Counter.objects.annotate_has_barman(self.barmen)
|
counters = Counter.objects.annotate_has_barman(self.barmen)
|
||||||
@@ -760,10 +786,10 @@ class TestBarmanConnection(TestCase):
|
|||||||
assert last_perm.counter == self.counter
|
assert last_perm.counter == self.counter
|
||||||
assert last_perm.user == self.barman
|
assert last_perm.user == self.barman
|
||||||
assert last_perm.end is None
|
assert last_perm.end is None
|
||||||
assert self.barman in response.wsgi_request.barmen
|
|
||||||
response = self.client.get(
|
response = self.client.get(
|
||||||
self.detail_url, {"username": self.barman.username, "password": "plop"}
|
self.detail_url, {"username": self.barman.username, "password": "plop"}
|
||||||
)
|
)
|
||||||
|
assert self.barman in response.wsgi_request.barmen
|
||||||
assert response.context_data.get("barmen") == [self.barman]
|
assert response.context_data.get("barmen") == [self.barman]
|
||||||
soup = BeautifulSoup(response.text, "lxml")
|
soup = BeautifulSoup(response.text, "lxml")
|
||||||
assert soup.find("form", id="select-user-form") is not None
|
assert soup.find("form", id="select-user-form") is not None
|
||||||
@@ -804,6 +830,41 @@ class TestBarmanConnection(TestCase):
|
|||||||
)
|
)
|
||||||
self.assert_counter_login_fails(self.barman)
|
self.assert_counter_login_fails(self.barman)
|
||||||
|
|
||||||
|
def test_barman_already_logged_in_another_device(self):
|
||||||
|
"""Test when the barman is already logged in the current counter on another device."""
|
||||||
|
other_client = Client()
|
||||||
|
other_client.post(
|
||||||
|
self.login_url, {"username": self.barman.username, "password": "plop"}
|
||||||
|
)
|
||||||
|
self.assert_counter_login_fails(self.barman)
|
||||||
|
|
||||||
|
def test_barman_login_elsewhere(self):
|
||||||
|
"""Test when the barman log himself out then log in on another device."""
|
||||||
|
self.client.post(
|
||||||
|
self.login_url, {"username": self.barman.username, "password": "plop"}
|
||||||
|
)
|
||||||
|
other_client = Client()
|
||||||
|
other_client.post(
|
||||||
|
reverse("counter:logout", kwargs={"counter_id": self.counter.id}),
|
||||||
|
data={"user_id": self.barman.id},
|
||||||
|
)
|
||||||
|
response = other_client.post(
|
||||||
|
self.login_url, {"username": self.barman.username, "password": "plop"}
|
||||||
|
)
|
||||||
|
assert response.status_code == 200
|
||||||
|
assert response.headers["HX-Redirect"] == self.detail_url
|
||||||
|
# the barmen should now be logged in `other_client`...
|
||||||
|
response = other_client.get(
|
||||||
|
self.detail_url, {"username": self.barman.username, "password": "plop"}
|
||||||
|
)
|
||||||
|
assert self.barman in response.wsgi_request.barmen
|
||||||
|
|
||||||
|
# ... but not in `self.client`
|
||||||
|
response = self.client.get(
|
||||||
|
self.detail_url, {"username": self.barman.username, "password": "plop"}
|
||||||
|
)
|
||||||
|
assert self.barman not in response.wsgi_request.barmen
|
||||||
|
|
||||||
def test_barman_already_logged_elsewhere(self):
|
def test_barman_already_logged_elsewhere(self):
|
||||||
"""Test when the barman is already logged in another counter."""
|
"""Test when the barman is already logged in another counter."""
|
||||||
other_counter = baker.make(Counter, type="BAR")
|
other_counter = baker.make(Counter, type="BAR")
|
||||||
|
|||||||
@@ -15,6 +15,7 @@ from core.models import User
|
|||||||
from counter.baker_recipes import product_recipe, refill_recipe, sale_recipe
|
from counter.baker_recipes import product_recipe, refill_recipe, sale_recipe
|
||||||
from counter.models import (
|
from counter.models import (
|
||||||
Counter,
|
Counter,
|
||||||
|
CounterSellers,
|
||||||
Customer,
|
Customer,
|
||||||
Refilling,
|
Refilling,
|
||||||
ReturnableProduct,
|
ReturnableProduct,
|
||||||
@@ -38,7 +39,7 @@ class TestStudentCard(TestCase):
|
|||||||
cls.subscriber = subscriber_user.make()
|
cls.subscriber = subscriber_user.make()
|
||||||
|
|
||||||
cls.counter = baker.make(Counter, type="BAR")
|
cls.counter = baker.make(Counter, type="BAR")
|
||||||
cls.counter.sellers.add(cls.barmen)
|
CounterSellers.objects.create(counter=cls.counter, user=cls.barmen)
|
||||||
|
|
||||||
cls.club_counter = baker.make(Counter)
|
cls.club_counter = baker.make(Counter)
|
||||||
role = baker.make(ClubRole, club=cls.club_counter.club, is_board=True)
|
role = baker.make(ClubRole, club=cls.club_counter.club, is_board=True)
|
||||||
|
|||||||
+22
-17
@@ -24,7 +24,7 @@ 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.safestring import SafeString
|
||||||
from django.utils.translation import gettext as _
|
from django.utils.translation import gettext as _
|
||||||
from django.views.generic import 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 ninja.main import HttpRequest
|
||||||
|
|
||||||
@@ -32,7 +32,14 @@ from core.auth.mixins import CanViewMixin
|
|||||||
from core.models import User
|
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 Counter, Customer, ProductFormula, ReturnableProduct, Selling
|
from counter.models import (
|
||||||
|
Counter,
|
||||||
|
Customer,
|
||||||
|
ProductFormula,
|
||||||
|
Refilling,
|
||||||
|
ReturnableProduct,
|
||||||
|
Selling,
|
||||||
|
)
|
||||||
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
|
||||||
from counter.views.student_card import StudentCardFormFragment
|
from counter.views.student_card import StudentCardFormFragment
|
||||||
@@ -66,13 +73,13 @@ class CounterClick(
|
|||||||
current_tab = "counter"
|
current_tab = "counter"
|
||||||
|
|
||||||
def get_form_kwargs(self):
|
def get_form_kwargs(self):
|
||||||
kwargs = super().get_form_kwargs()
|
return super().get_form_kwargs() | {
|
||||||
kwargs["form_kwargs"] = {
|
|
||||||
"customer": self.customer,
|
"customer": self.customer,
|
||||||
"counter": self.object,
|
"counter": self.object,
|
||||||
"allowed_prices": {price.id: price for price in self.prices},
|
"form_kwargs": {
|
||||||
|
"allowed_prices": {price.id: price for price in self.prices}
|
||||||
|
},
|
||||||
}
|
}
|
||||||
return kwargs
|
|
||||||
|
|
||||||
def dispatch(self, request, *args, **kwargs):
|
def dispatch(self, request, *args, **kwargs):
|
||||||
self.customer = get_object_or_404(Customer, user_id=self.kwargs["user_id"])
|
self.customer = get_object_or_404(Customer, user_id=self.kwargs["user_id"])
|
||||||
@@ -219,9 +226,10 @@ class CounterClick(
|
|||||||
return kwargs
|
return kwargs
|
||||||
|
|
||||||
|
|
||||||
class RefillingCreateView(FragmentMixin, FormView):
|
class RefillingCreateView(FragmentMixin, CreateView):
|
||||||
"""This is a fragment only view which integrates with counter_click.jinja"""
|
"""This is a fragment only view which integrates with counter_click.jinja"""
|
||||||
|
|
||||||
|
model = Refilling
|
||||||
form_class = RefillForm
|
form_class = RefillForm
|
||||||
template_name = "counter/fragments/create_refill.jinja"
|
template_name = "counter/fragments/create_refill.jinja"
|
||||||
|
|
||||||
@@ -242,23 +250,20 @@ class RefillingCreateView(FragmentMixin, FormView):
|
|||||||
):
|
):
|
||||||
raise PermissionDenied
|
raise PermissionDenied
|
||||||
|
|
||||||
self.operator = get_operator(request, self.counter, self.customer)
|
|
||||||
|
|
||||||
return super().dispatch(request, *args, **kwargs)
|
return super().dispatch(request, *args, **kwargs)
|
||||||
|
|
||||||
def render_fragment(self, request, **kwargs) -> SafeString:
|
def render_fragment(self, request, **kwargs) -> SafeString:
|
||||||
self.customer = kwargs.pop("customer")
|
self.customer = kwargs.pop("customer")
|
||||||
self.counter = kwargs.pop("counter")
|
self.counter = kwargs.pop("counter")
|
||||||
|
self.object = None
|
||||||
return super().render_fragment(request, **kwargs)
|
return super().render_fragment(request, **kwargs)
|
||||||
|
|
||||||
def form_valid(self, form):
|
def get_form_kwargs(self):
|
||||||
res = super().form_valid(form)
|
return super().get_form_kwargs() | {
|
||||||
form.clean()
|
"counter": self.counter,
|
||||||
form.instance.counter = self.counter
|
"operator": get_operator(self.request, self.counter, self.customer),
|
||||||
form.instance.operator = self.operator
|
"customer": self.customer,
|
||||||
form.instance.customer = self.customer
|
}
|
||||||
form.instance.save()
|
|
||||||
return res
|
|
||||||
|
|
||||||
def get_context_data(self, **kwargs):
|
def get_context_data(self, **kwargs):
|
||||||
kwargs = super().get_context_data(**kwargs)
|
kwargs = super().get_context_data(**kwargs)
|
||||||
|
|||||||
@@ -30,6 +30,7 @@ from django.views.generic.edit import FormView
|
|||||||
from core.auth.mixins import CanViewMixin
|
from core.auth.mixins import CanViewMixin
|
||||||
from core.views import FragmentMixin, UseFragmentsMixin
|
from core.views import FragmentMixin, UseFragmentsMixin
|
||||||
from counter.forms import CounterLoginForm, GetUserForm
|
from counter.forms import CounterLoginForm, GetUserForm
|
||||||
|
from counter.middleware import SESSION_PERMANENCES_KEY
|
||||||
from counter.models import Counter, Permanency
|
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
|
||||||
@@ -58,8 +59,8 @@ class CounterLoginFragment(FragmentMixin, SingleObjectMixin, FormView):
|
|||||||
|
|
||||||
def form_valid(self, form: CounterLoginForm):
|
def form_valid(self, form: CounterLoginForm):
|
||||||
user = form.get_user()
|
user = form.get_user()
|
||||||
self.object.permanencies.create(user=user, start=timezone.now())
|
perm = self.object.permanencies.create(user=user, start=timezone.now())
|
||||||
self.request.barmen.add(user)
|
self.request.session.setdefault(SESSION_PERMANENCES_KEY, []).append(perm.id)
|
||||||
self.success_url = reverse(
|
self.success_url = reverse(
|
||||||
"counter:details", kwargs={"counter_id": self.object.id}
|
"counter:details", kwargs={"counter_id": self.object.id}
|
||||||
)
|
)
|
||||||
|
|||||||
@@ -5,10 +5,11 @@ interface BasketItem {
|
|||||||
name: string;
|
name: string;
|
||||||
quantity: number;
|
quantity: number;
|
||||||
unitPrice: number;
|
unitPrice: number;
|
||||||
|
isRefill: boolean;
|
||||||
}
|
}
|
||||||
|
|
||||||
const BASKET_CACHE_KEY = "basket";
|
const BASKET_CACHE_KEY = "basket";
|
||||||
const BASKET_CACHE_VERSION = 1;
|
const BASKET_CACHE_VERSION = 2;
|
||||||
|
|
||||||
document.addEventListener("alpine:init", () => {
|
document.addEventListener("alpine:init", () => {
|
||||||
Alpine.data("basket", (validPrices: number[], lastPurchaseTime?: number) => ({
|
Alpine.data("basket", (validPrices: number[], lastPurchaseTime?: number) => ({
|
||||||
@@ -21,7 +22,7 @@ document.addEventListener("alpine:init", () => {
|
|||||||
});
|
});
|
||||||
document
|
document
|
||||||
.getElementById("id_form-TOTAL_FORMS")
|
.getElementById("id_form-TOTAL_FORMS")
|
||||||
.setAttribute(":value", "basket.length");
|
?.setAttribute(":value", "basket.length");
|
||||||
},
|
},
|
||||||
|
|
||||||
loadBasket(): BasketItem[] {
|
loadBasket(): BasketItem[] {
|
||||||
@@ -32,8 +33,8 @@ document.addEventListener("alpine:init", () => {
|
|||||||
return [];
|
return [];
|
||||||
}
|
}
|
||||||
if (
|
if (
|
||||||
lastPurchaseTime !== null &&
|
lastPurchaseTime &&
|
||||||
localStorage.basketTimestamp !== undefined &&
|
localStorage.basketTimestamp &&
|
||||||
new Date(lastPurchaseTime) >=
|
new Date(lastPurchaseTime) >=
|
||||||
new Date(Number.parseInt(localStorage.basketTimestamp, 10))
|
new Date(Number.parseInt(localStorage.basketTimestamp, 10))
|
||||||
) {
|
) {
|
||||||
@@ -64,6 +65,19 @@ document.addEventListener("alpine:init", () => {
|
|||||||
);
|
);
|
||||||
},
|
},
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get the total of money that would be added to the AE account on basket purchase.
|
||||||
|
*/
|
||||||
|
getTotalAdded() {
|
||||||
|
return this.basket
|
||||||
|
.filter((item) => item.isRefill || item.unitPrice < 0)
|
||||||
|
.reduce(
|
||||||
|
(acc: number, item: BasketItem) =>
|
||||||
|
acc + Math.abs(item.quantity * item.unitPrice),
|
||||||
|
0,
|
||||||
|
);
|
||||||
|
},
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Add 1 to the quantity of an item in the basket
|
* Add 1 to the quantity of an item in the basket
|
||||||
* @param {BasketItem} item
|
* @param {BasketItem} item
|
||||||
@@ -86,7 +100,7 @@ document.addEventListener("alpine:init", () => {
|
|||||||
|
|
||||||
if (this.basket[index].quantity === 0) {
|
if (this.basket[index].quantity === 0) {
|
||||||
this.basket = this.basket.filter(
|
this.basket = this.basket.filter(
|
||||||
(e: BasketItem) => e.priceId !== this.basket[index].id,
|
(e: BasketItem) => e.priceId !== this.basket[index].priceId,
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
@@ -103,14 +117,16 @@ document.addEventListener("alpine:init", () => {
|
|||||||
* @param id The id of the product to add
|
* @param id The id of the product to add
|
||||||
* @param name The name of the product
|
* @param name The name of the product
|
||||||
* @param price The unit price of the product
|
* @param price The unit price of the product
|
||||||
|
* @param isRefill true if the product is a refill bond
|
||||||
* @returns The created item
|
* @returns The created item
|
||||||
*/
|
*/
|
||||||
createItem(id: number, name: string, price: number): BasketItem {
|
createItem(id: number, name: string, price: number, isRefill: boolean): BasketItem {
|
||||||
const newItem = {
|
const newItem = {
|
||||||
priceId: id,
|
priceId: id,
|
||||||
name,
|
name,
|
||||||
quantity: 0,
|
quantity: 0,
|
||||||
unitPrice: price,
|
unitPrice: price,
|
||||||
|
isRefill,
|
||||||
} as BasketItem;
|
} as BasketItem;
|
||||||
|
|
||||||
this.basket.push(newItem);
|
this.basket.push(newItem);
|
||||||
@@ -125,16 +141,17 @@ document.addEventListener("alpine:init", () => {
|
|||||||
* @param id The id of the product to add
|
* @param id The id of the product to add
|
||||||
* @param name The name of the product
|
* @param name The name of the product
|
||||||
* @param price The unit price of the product
|
* @param price The unit price of the product
|
||||||
|
* @param isRefill true if the product is a refill bond
|
||||||
*/
|
*/
|
||||||
addFromCatalog(id: number, name: string, price: number) {
|
addFromCatalog(id: number, name: string, price: number, isRefill: boolean) {
|
||||||
let item = this.basket.find((e: BasketItem) => e.priceId === id);
|
const item = this.basket.find((e: BasketItem) => e.priceId === id);
|
||||||
|
|
||||||
// if the item is not in the basket, we create it
|
// if the item is not in the basket, we create it
|
||||||
// else we add + 1 to it
|
// else we add + 1 to it
|
||||||
if (item) {
|
if (item) {
|
||||||
this.add(item);
|
this.add(item);
|
||||||
} else {
|
} else {
|
||||||
item = this.createItem(id, name, price);
|
this.createItem(id, name, price, isRefill);
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
}));
|
}));
|
||||||
|
|||||||
@@ -58,6 +58,17 @@
|
|||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
{% endif %}
|
{% endif %}
|
||||||
|
<template x-if="(getTotalAdded() + {{ customer_amount }}) > {{ settings.SITH_ACCOUNT_MAX_MONEY }}">
|
||||||
|
<div class="alert alert-red">
|
||||||
|
<div class="alert-main">
|
||||||
|
{% trans trimmed limit=settings.SITH_ACCOUNT_MAX_MONEY %}
|
||||||
|
You cannot purchase the current basket,
|
||||||
|
because it would put your AE account balance
|
||||||
|
above the {{ limit }}€ limit
|
||||||
|
{% endtrans %}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
<ul class="item-list">
|
<ul class="item-list">
|
||||||
{# Starting money #}
|
{# Starting money #}
|
||||||
<li>
|
<li>
|
||||||
@@ -109,9 +120,12 @@
|
|||||||
<i class="fa fa-trash"></i>
|
<i class="fa fa-trash"></i>
|
||||||
{% trans %}Clear{% endtrans %}
|
{% trans %}Clear{% endtrans %}
|
||||||
</button>
|
</button>
|
||||||
<button class="btn btn-blue">
|
<button
|
||||||
|
class="btn btn-blue"
|
||||||
|
:disabled="(getTotalAdded() + {{ customer_amount }}) > {{ settings.SITH_ACCOUNT_MAX_MONEY }}"
|
||||||
|
>
|
||||||
<i class="fa fa-check"></i>
|
<i class="fa fa-check"></i>
|
||||||
<input type="submit" value="{% trans %}Validate{% endtrans %}"/>
|
{% trans %}Validate{% endtrans %}
|
||||||
</button>
|
</button>
|
||||||
</div>
|
</div>
|
||||||
</form>
|
</form>
|
||||||
@@ -199,7 +213,12 @@
|
|||||||
id="{{ price.id }}"
|
id="{{ price.id }}"
|
||||||
class="card clickable shadow"
|
class="card clickable shadow"
|
||||||
:class="{selected: basket.some((i) => i.priceId === {{ price.id }})}"
|
:class="{selected: basket.some((i) => i.priceId === {{ price.id }})}"
|
||||||
@click='addFromCatalog({{ price.id }}, {{ price.full_label|tojson }}, {{ price.amount }})'
|
@click='addFromCatalog(
|
||||||
|
{{ price.id }},
|
||||||
|
{{ price.full_label|tojson }},
|
||||||
|
{{ price.amount }},
|
||||||
|
{{ (price.product.product_type_id == settings.SITH_COUNTER_PRODUCTTYPE_REFILLING)|lower }}
|
||||||
|
)'
|
||||||
{% if price.sold_out %}disabled{% endif %}
|
{% if price.sold_out %}disabled{% endif %}
|
||||||
>
|
>
|
||||||
{% if price.product.icon %}
|
{% if price.product.icon %}
|
||||||
|
|||||||
@@ -278,6 +278,27 @@ class TestEboutic(TestCase):
|
|||||||
)
|
)
|
||||||
assert Basket.objects.count() == 2
|
assert Basket.objects.count() == 2
|
||||||
|
|
||||||
|
def test_refill_limit(self):
|
||||||
|
"""Test that an eboutic basket cannot refill an account above the limit."""
|
||||||
|
self.client.force_login(self.subscriber)
|
||||||
|
product = product_recipe.make(
|
||||||
|
product_type_id=settings.SITH_COUNTER_PRODUCTTYPE_REFILLING,
|
||||||
|
counters=[self.eboutic],
|
||||||
|
)
|
||||||
|
price = price_recipe.make(
|
||||||
|
product=product,
|
||||||
|
groups=[self.group_cotiz],
|
||||||
|
amount=settings.SITH_ACCOUNT_MAX_MONEY // 10,
|
||||||
|
)
|
||||||
|
|
||||||
|
response = self.submit_basket([BasketItem(price.id, 10)])
|
||||||
|
assert Basket.objects.count() == 1
|
||||||
|
assertRedirects(response, reverse("eboutic:checkout", kwargs={"basket_id": 1}))
|
||||||
|
|
||||||
|
response = self.submit_basket([BasketItem(price.id, 11)])
|
||||||
|
assert Basket.objects.count() == 1
|
||||||
|
assert response.status_code == 200 # no redirect = form validation failed
|
||||||
|
|
||||||
def test_create_basket(self):
|
def test_create_basket(self):
|
||||||
self.client.force_login(self.new_customer)
|
self.client.force_login(self.new_customer)
|
||||||
assertRedirects(
|
assertRedirects(
|
||||||
|
|||||||
+6
-8
@@ -66,9 +66,7 @@ if TYPE_CHECKING:
|
|||||||
|
|
||||||
|
|
||||||
class BaseEbouticBasketForm(BaseBasketForm):
|
class BaseEbouticBasketForm(BaseBasketForm):
|
||||||
def _check_enough_money(self, *args, **kwargs):
|
min_result_balance = None # user can pay by card, so no minimum enforced
|
||||||
# Disable money check
|
|
||||||
...
|
|
||||||
|
|
||||||
|
|
||||||
EbouticBasketForm = forms.formset_factory(
|
EbouticBasketForm = forms.formset_factory(
|
||||||
@@ -88,15 +86,15 @@ class EbouticMainView(LoginRequiredMixin, FormView):
|
|||||||
form_class = EbouticBasketForm
|
form_class = EbouticBasketForm
|
||||||
|
|
||||||
def get_form_kwargs(self):
|
def get_form_kwargs(self):
|
||||||
kwargs = super().get_form_kwargs()
|
return super().get_form_kwargs() | {
|
||||||
kwargs["form_kwargs"] = {
|
|
||||||
"customer": self.customer,
|
"customer": self.customer,
|
||||||
"counter": get_eboutic(),
|
"counter": get_eboutic(),
|
||||||
"allowed_prices": {
|
"form_kwargs": {
|
||||||
price.id: price for price in self.prices if not price.sold_out
|
"allowed_prices": {
|
||||||
|
price.id: price for price in self.prices if not price.sold_out
|
||||||
|
}
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
return kwargs
|
|
||||||
|
|
||||||
def form_valid(self, formset):
|
def form_valid(self, formset):
|
||||||
if len(formset) == 0:
|
if len(formset) == 0:
|
||||||
|
|||||||
@@ -251,8 +251,12 @@ class ApplyElectionResultForm(forms.Form):
|
|||||||
user_id=c.user_id,
|
user_id=c.user_id,
|
||||||
club_id=c.role.club_role.club_id,
|
club_id=c.role.club_role.club_id,
|
||||||
role=c.role.club_role,
|
role=c.role.club_role,
|
||||||
|
description=(
|
||||||
|
c.role.title if c.role.title != c.role.club_role.name else ""
|
||||||
|
),
|
||||||
)
|
)
|
||||||
for c in candidates
|
for c in candidates
|
||||||
]
|
]
|
||||||
Membership.objects.bulk_create(memberships)
|
Membership.objects.bulk_create(memberships)
|
||||||
Membership._add_club_groups(memberships)
|
Membership._add_club_groups(memberships)
|
||||||
|
return memberships
|
||||||
|
|||||||
@@ -13,6 +13,7 @@ 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
|
||||||
from core.models import Group, User
|
from core.models import Group, User
|
||||||
|
from election.forms import ApplyElectionResultForm
|
||||||
from election.models import Candidature, Election, ElectionList, Role, Vote
|
from election.models import Candidature, Election, ElectionList, Role, Vote
|
||||||
|
|
||||||
|
|
||||||
@@ -155,6 +156,19 @@ class TestApplyResult(TestCase):
|
|||||||
response = self.client.post(self.url, data={"candidates": ids})
|
response = self.client.post(self.url, data={"candidates": ids})
|
||||||
assert response.status_code == 403
|
assert response.status_code == 403
|
||||||
|
|
||||||
|
def test_membership_description(self):
|
||||||
|
"""Test that if club role name and election role name are different,
|
||||||
|
then the election role name is used as membership description.
|
||||||
|
"""
|
||||||
|
form = ApplyElectionResultForm(
|
||||||
|
election=self.election, data={"candidates": [self.candidatures[0].id]}
|
||||||
|
)
|
||||||
|
assert form.is_valid()
|
||||||
|
memberships = form.save()
|
||||||
|
assert len(memberships) == 1
|
||||||
|
assert memberships[0].role == self.club_roles[0]
|
||||||
|
assert memberships[0].description == "election role 1"
|
||||||
|
|
||||||
def test_no_result_to_apply(self):
|
def test_no_result_to_apply(self):
|
||||||
self.election.roles.update(club_role=None)
|
self.election.roles.update(club_role=None)
|
||||||
user = baker.make(
|
user = baker.make(
|
||||||
|
|||||||
@@ -6,7 +6,7 @@
|
|||||||
msgid ""
|
msgid ""
|
||||||
msgstr ""
|
msgstr ""
|
||||||
"Report-Msgid-Bugs-To: \n"
|
"Report-Msgid-Bugs-To: \n"
|
||||||
"POT-Creation-Date: 2026-06-05 13:39+0200\n"
|
"POT-Creation-Date: 2026-06-10 20:18+0200\n"
|
||||||
"PO-Revision-Date: 2016-07-18\n"
|
"PO-Revision-Date: 2016-07-18\n"
|
||||||
"Last-Translator: Maréchal <thomas.girod@utbm.fr\n"
|
"Last-Translator: Maréchal <thomas.girod@utbm.fr\n"
|
||||||
"Language-Team: AE info <ae.info@utbm.fr>\n"
|
"Language-Team: AE info <ae.info@utbm.fr>\n"
|
||||||
@@ -3217,6 +3217,10 @@ msgstr "Vous êtes déjà connecté à ce comptoir."
|
|||||||
msgid "You are already logged in another counter."
|
msgid "You are already logged in another counter."
|
||||||
msgstr "Vous êtes déjà connecté à un autre comptoir."
|
msgstr "Vous êtes déjà connecté à un autre comptoir."
|
||||||
|
|
||||||
|
#: counter/forms.py
|
||||||
|
msgid "You are already logged on another device"
|
||||||
|
msgstr "Vous êtes déjà connecté sur un autre appareil"
|
||||||
|
|
||||||
#: counter/forms.py
|
#: counter/forms.py
|
||||||
msgid "Regular barmen"
|
msgid "Regular barmen"
|
||||||
msgstr "Barmen réguliers"
|
msgstr "Barmen réguliers"
|
||||||
@@ -3306,6 +3310,11 @@ msgstr "Saisie de produit dupliquée"
|
|||||||
msgid "Not enough money"
|
msgid "Not enough money"
|
||||||
msgstr "Solde insuffisant"
|
msgstr "Solde insuffisant"
|
||||||
|
|
||||||
|
#: counter/forms.py counter/models.py
|
||||||
|
#, python-format
|
||||||
|
msgid "There cannot be more than %(money)d€ on an AE account"
|
||||||
|
msgstr "Il ne peut pas y avoir plus de %(money)d€ sur un compte AE"
|
||||||
|
|
||||||
#: counter/forms.py
|
#: counter/forms.py
|
||||||
#, python-format
|
#, python-format
|
||||||
msgid ""
|
msgid ""
|
||||||
@@ -4428,6 +4437,15 @@ msgstr "Payer avec un compte AE"
|
|||||||
msgid "The online shop of the association."
|
msgid "The online shop of the association."
|
||||||
msgstr "La boutique en ligne de l'association."
|
msgstr "La boutique en ligne de l'association."
|
||||||
|
|
||||||
|
#: eboutic/templates/eboutic/eboutic_main.jinja
|
||||||
|
#, python-format
|
||||||
|
msgid ""
|
||||||
|
"You cannot purchase the current basket, because it would put your AE account "
|
||||||
|
"balance above the %(limit)s€ limit"
|
||||||
|
msgstr ""
|
||||||
|
"Vous ne pouvez pas finaliser le panier actuel, parce que le solde de votre "
|
||||||
|
"compte AE passerait au-dessus de la limite de %(limit)s€."
|
||||||
|
|
||||||
#: eboutic/templates/eboutic/eboutic_main.jinja
|
#: eboutic/templates/eboutic/eboutic_main.jinja
|
||||||
msgid "Clear"
|
msgid "Clear"
|
||||||
msgstr "Vider"
|
msgstr "Vider"
|
||||||
|
|||||||
Generated
+995
-1170
File diff suppressed because it is too large
Load Diff
+10
-10
@@ -24,10 +24,10 @@
|
|||||||
"#com:*": "./com/static/bundled/*"
|
"#com:*": "./com/static/bundled/*"
|
||||||
},
|
},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"@babel/core": "^7.29.7",
|
"@babel/core": "^8.0.1",
|
||||||
"@babel/preset-env": "^7.29.7",
|
"@babel/preset-env": "^8.0.2",
|
||||||
"@biomejs/biome": "^2.4.16",
|
"@biomejs/biome": "^2.5.1",
|
||||||
"@hey-api/openapi-ts": "^0.98.1",
|
"@hey-api/openapi-ts": "^0.99.0",
|
||||||
"@types/alpinejs": "^3.13.11",
|
"@types/alpinejs": "^3.13.11",
|
||||||
"@types/alpinejs__sort": "^3.13.0",
|
"@types/alpinejs__sort": "^3.13.0",
|
||||||
"@types/cytoscape-cxtmenu": "^3.4.5",
|
"@types/cytoscape-cxtmenu": "^3.4.5",
|
||||||
@@ -35,18 +35,18 @@
|
|||||||
"@types/js-cookie": "^3.0.6",
|
"@types/js-cookie": "^3.0.6",
|
||||||
"rollup-plugin-visualizer": "^7.0.1",
|
"rollup-plugin-visualizer": "^7.0.1",
|
||||||
"typescript": "^6.0.3",
|
"typescript": "^6.0.3",
|
||||||
"vite": "^8.0.16"
|
"vite": "^8.1.0"
|
||||||
},
|
},
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@alpinejs/sort": "^3.15.12",
|
"@alpinejs/sort": "^3.15.12",
|
||||||
"@arendjr/text-clipper": "npm:@jsr/arendjr__text-clipper@^3.0.0",
|
"@arendjr/text-clipper": "npm:@jsr/arendjr__text-clipper@^3.0.0",
|
||||||
"@floating-ui/dom": "^1.7.6",
|
"@floating-ui/dom": "^1.7.6",
|
||||||
"@fortawesome/fontawesome-free": "^7.2.0",
|
"@fortawesome/fontawesome-free": "^7.2.0",
|
||||||
"@fullcalendar/core": "^6.1.20",
|
"@fullcalendar/core": "^6.1.21",
|
||||||
"@fullcalendar/daygrid": "^6.1.20",
|
"@fullcalendar/daygrid": "^6.1.21",
|
||||||
"@fullcalendar/icalendar": "^6.1.20",
|
"@fullcalendar/icalendar": "^6.1.21",
|
||||||
"@fullcalendar/list": "^6.1.20",
|
"@fullcalendar/list": "^6.1.21",
|
||||||
"@sentry/browser": "^10.56.0",
|
"@sentry/browser": "^10.60.0",
|
||||||
"@zip.js/zip.js": "^2.8.26",
|
"@zip.js/zip.js": "^2.8.26",
|
||||||
"3d-force-graph": "^1.80.0",
|
"3d-force-graph": "^1.80.0",
|
||||||
"alpinejs": "^3.15.12",
|
"alpinejs": "^3.15.12",
|
||||||
|
|||||||
+15
-15
@@ -21,31 +21,31 @@ requires-python = "<4.0,>=3.12"
|
|||||||
dependencies = [
|
dependencies = [
|
||||||
"django>=5.2.15,<6.0.0",
|
"django>=5.2.15,<6.0.0",
|
||||||
"django-ninja>=1.6.2,<2.0.0",
|
"django-ninja>=1.6.2,<2.0.0",
|
||||||
"django-ninja-extra>=0.31.4",
|
"django-ninja-extra>=0.31.5",
|
||||||
"Pillow>=12.2.0,<13.0.0",
|
"Pillow>=12.2.0,<13.0.0",
|
||||||
"mistune>=3.2.1,<4.0.0",
|
"aemark>=0.1.1",
|
||||||
"django-jinja<3.0.0,>=2.11.0",
|
"django-jinja<3.0.0,>=2.11.0",
|
||||||
"cryptography>=48.0.0,<49.0.0",
|
"cryptography>=49.0.0,<50.0.0",
|
||||||
"django-phonenumber-field>=8.4.0,<9.0.0",
|
"django-phonenumber-field>=8.4.0,<9.0.0",
|
||||||
"phonenumbers>=9.0.32,<10.0.0",
|
"phonenumbers>=9.0.33,<10.0.0",
|
||||||
"reportlab>=4.5.1,<5.0.0",
|
"reportlab>=5.0.0,<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.6.3,<1.0.0",
|
"django-simple-captcha>=0.6.3,<1.0.0",
|
||||||
"python-dateutil>=2.9.0.post0,<3.0.0.0",
|
"python-dateutil>=2.9.0.post0,<3.0.0.0",
|
||||||
"sentry-sdk>=2.61.1,<3.0.0",
|
"sentry-sdk>=2.63.0,<3.0.0",
|
||||||
"jinja2>=3.1.6,<4.0.0",
|
"jinja2>=3.1.6,<4.0.0",
|
||||||
"django-countries>=8.2.0,<9.0.0",
|
"django-countries>=9.0.0,<10.0.0",
|
||||||
"dict2xml>=1.7.8,<2.0.0",
|
"dict2xml>=1.7.8,<2.0.0",
|
||||||
"Sphinx>=9.1.0,<10", # Used by xapian during installation
|
"Sphinx>=9.1.0,<10", # Used by xapian during installation
|
||||||
"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>=12.0.0,<14.0.0",
|
"ical>=12.0.0,<14.0.0",
|
||||||
"redis[hiredis]>=3.4.0,<8.0.0",
|
"redis[hiredis]>=6.4.0,<9.0.0",
|
||||||
"environs[django]>=6.0.5,<16",
|
"environs[django]>=15.0.1,<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",
|
||||||
@@ -63,21 +63,21 @@ prod = [
|
|||||||
"psycopg[c]>=3.3.4,<4.0.0",
|
"psycopg[c]>=3.3.4,<4.0.0",
|
||||||
]
|
]
|
||||||
dev = [
|
dev = [
|
||||||
"django-debug-toolbar>=6.3.0,<7",
|
"django-debug-toolbar>=7.0.0,<8",
|
||||||
"ipython>=9.14.1,<10.0.0",
|
"ipython>=9.14.1,<10.0.0",
|
||||||
"pre-commit>=4.6.0,<5.0.0",
|
"pre-commit>=4.6.0,<5.0.0",
|
||||||
"ruff>=0.15.16,<1.0.0",
|
"ruff>=0.15.19,<1.0.0",
|
||||||
"djhtml>=3.0.11,<4.0.0",
|
"djhtml>=3.0.11,<4.0.0",
|
||||||
"faker>=40.21.0,<41.0.0",
|
"faker>=40.23.0,<41.0.0",
|
||||||
"rjsmin>=1.2.5,<2.0.0",
|
"rjsmin>=1.2.5,<2.0.0",
|
||||||
]
|
]
|
||||||
tests = [
|
tests = [
|
||||||
"freezegun>=1.5.5,<2.0.0",
|
"freezegun>=1.5.5,<2.0.0",
|
||||||
"pytest>=9.0.3,<10.0.0",
|
"pytest>=9.1.1,<10.0.0",
|
||||||
"pytest-cov>=7.1.0,<8.0.0",
|
"pytest-cov>=7.1.0,<8.0.0",
|
||||||
"pytest-django>=4.12.0,<5.0.0",
|
"pytest-django>=4.12.0,<5.0.0",
|
||||||
"model-bakery>=1.23.4,<2.0.0",
|
"model-bakery>=1.24.0,<2.0.0",
|
||||||
"beautifulsoup4>=4.14.3,<5",
|
"beautifulsoup4>=4.15.0,<5",
|
||||||
"lxml>=6.1.1,<7",
|
"lxml>=6.1.1,<7",
|
||||||
]
|
]
|
||||||
docs = [
|
docs = [
|
||||||
|
|||||||
@@ -63,7 +63,7 @@ class PictureWithIdentifications {
|
|||||||
if (this.identificationsLoading) {
|
if (this.identificationsLoading) {
|
||||||
return; // The users are already being fetched.
|
return; // The users are already being fetched.
|
||||||
}
|
}
|
||||||
if (!!this.identifications && !options?.forceReload) {
|
if (this.identifications && !options?.forceReload) {
|
||||||
// The users are already fetched
|
// The users are already fetched
|
||||||
// and the user does not want to force the reload
|
// and the user does not want to force the reload
|
||||||
return;
|
return;
|
||||||
@@ -82,7 +82,7 @@ class PictureWithIdentifications {
|
|||||||
if (this.moderationLoading) {
|
if (this.moderationLoading) {
|
||||||
return; // The moderation requests are already being fetched.
|
return; // The moderation requests are already being fetched.
|
||||||
}
|
}
|
||||||
if (!!this.moderationRequests && !options?.forceReload) {
|
if (this.moderationRequests && !options?.forceReload) {
|
||||||
// The moderation requests are already fetched
|
// The moderation requests are already fetched
|
||||||
// and the user does not want to force the reload
|
// and the user does not want to force the reload
|
||||||
return;
|
return;
|
||||||
|
|||||||
@@ -503,6 +503,12 @@ SITH_ACCOUNT_INACTIVITY_DELTA = relativedelta(years=2)
|
|||||||
SITH_ACCOUNT_DUMP_DELTA = timedelta(days=30)
|
SITH_ACCOUNT_DUMP_DELTA = timedelta(days=30)
|
||||||
"""timedelta between the warning mail and the actual account dump"""
|
"""timedelta between the warning mail and the actual account dump"""
|
||||||
|
|
||||||
|
SITH_ACCOUNT_MAX_MONEY = 250 # €
|
||||||
|
"""Maximum amount of money a sith account can hold.
|
||||||
|
|
||||||
|
This amount is defined by the AE's Terms and Conditions of Sale.
|
||||||
|
"""
|
||||||
|
|
||||||
# Defines which product type is the refilling type,
|
# Defines which product type is the refilling type,
|
||||||
# and thus increases the account amount
|
# and thus increases the account amount
|
||||||
SITH_COUNTER_PRODUCTTYPE_REFILLING = env.int(
|
SITH_COUNTER_PRODUCTTYPE_REFILLING = env.int(
|
||||||
|
|||||||
@@ -6,6 +6,71 @@ resolution-markers = [
|
|||||||
"python_full_version < '3.13'",
|
"python_full_version < '3.13'",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "aemark"
|
||||||
|
version = "0.1.1"
|
||||||
|
source = { registry = "https://pypi.org/simple" }
|
||||||
|
sdist = { url = "https://files.pythonhosted.org/packages/11/97/35c298a8557d58f10402f40cc04d8bccba8dd2ab5c89bbbb41ce82f9ae29/aemark-0.1.1.tar.gz", hash = "sha256:01c19374553a1fc4ec5b5b0609a28dea8e724395c4383e2c41e292ee9bf1b9b2", size = 32558, upload-time = "2026-06-19T10:10:17.016Z" }
|
||||||
|
wheels = [
|
||||||
|
{ url = "https://files.pythonhosted.org/packages/ea/0c/b35426c7d1d52b6089d8d4fa8b50e1ca965475a42f000e4855468ea1889f/aemark-0.1.1-cp312-cp312-macosx_10_12_x86_64.whl", hash = "sha256:d79173c2c5311eea1f5043c24bfb7368ece6df1d041a3cbd51bbc54a3ca8f630", size = 467866, upload-time = "2026-06-19T10:09:09.99Z" },
|
||||||
|
{ url = "https://files.pythonhosted.org/packages/ec/b3/8f85ca830a2d3aae2f37383b3eab8d382e438f8c1f764517eaf10d1fd026/aemark-0.1.1-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:3d3facf829907cadabf2154a86c562fa05b8528f418f933d4517f8b6192bab0f", size = 455182, upload-time = "2026-06-19T10:09:11.172Z" },
|
||||||
|
{ url = "https://files.pythonhosted.org/packages/76/f2/9ff2fe99851e7c7c30da7d7791f3a21868f046b5f2bd326dd52e80d65aca/aemark-0.1.1-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:dbb356e5c208a8f0f4b725117a8075c6fc54911fc62fc7f974934402faa0bab7", size = 544038, upload-time = "2026-06-19T10:09:12.308Z" },
|
||||||
|
{ url = "https://files.pythonhosted.org/packages/ae/09/354c635e6f1bcc525ed8923f5f0ed7b7a95c12a5fa211ed4d827c16de41d/aemark-0.1.1-cp312-cp312-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:76615cd0fa97dd020aac3748c8fb9dda585d7eea0e151361f872628a1e70ee5a", size = 494693, upload-time = "2026-06-19T10:09:13.422Z" },
|
||||||
|
{ url = "https://files.pythonhosted.org/packages/a3/fb/cba45091950f393d909aa4df8df903e795c7b9ba64c208c03aa949b41f4f/aemark-0.1.1-cp312-cp312-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:7d79a1246166babf5266abd45c39cc584f30cef2a0b6f4cb38384ee63f559c62", size = 597809, upload-time = "2026-06-19T10:09:14.617Z" },
|
||||||
|
{ url = "https://files.pythonhosted.org/packages/53/06/9e403d55750f0c8797379a02bfc39931ccbb97622105b50e84cd6d9e863e/aemark-0.1.1-cp312-cp312-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:802234cbfd60ccd985ce4d6320217f3280319579590a6dd22383d1481130ad00", size = 654480, upload-time = "2026-06-19T10:09:16.078Z" },
|
||||||
|
{ url = "https://files.pythonhosted.org/packages/da/97/9feb3169899d444578f39d1caeab3d92b7e8d629d6a24d44bbda929bc4d0/aemark-0.1.1-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:b957e390ecd3d9ab22be61bf95214d33673fb2ed1a09617e1b443a8bba1a8cbc", size = 516859, upload-time = "2026-06-19T10:09:17.335Z" },
|
||||||
|
{ url = "https://files.pythonhosted.org/packages/b8/b4/f842b159b46ce4fd4271afaa9107517d5f69574c8ff057f9bd65f0b5805b/aemark-0.1.1-cp312-cp312-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:6947de45713b228190a7bddb52895a5c0b402ff00ff18acb967de7dceded1fa2", size = 518199, upload-time = "2026-06-19T10:09:18.327Z" },
|
||||||
|
{ url = "https://files.pythonhosted.org/packages/01/4f/1e1c1d68a4dbe9aea6b13e7e33bbf3ddd229a86a1fc75b7c2c71d48eb06a/aemark-0.1.1-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:8b633b0a171716424a84b44841c2f43f799da3fe04e3bd2ac356e587f333d98d", size = 720953, upload-time = "2026-06-19T10:09:19.527Z" },
|
||||||
|
{ url = "https://files.pythonhosted.org/packages/f5/e8/9b20d96bff485a0e5dabc610d1b7a47373d161b53f82d260b27ca2104b63/aemark-0.1.1-cp312-cp312-musllinux_1_2_armv7l.whl", hash = "sha256:abd49b2cf5af61cf2b8c2a6e45a87df055b003a45fd10a94a6022857af15a115", size = 771507, upload-time = "2026-06-19T10:09:20.742Z" },
|
||||||
|
{ url = "https://files.pythonhosted.org/packages/ce/8d/dd924c4bf790670a198b64b8d99e0d8b3f8a3462d96b241a759edb2bdfa5/aemark-0.1.1-cp312-cp312-musllinux_1_2_i686.whl", hash = "sha256:0d48f411e544724cb4c5b5932369785dc1c97d32e9f04cf664607f1e67a33874", size = 737232, upload-time = "2026-06-19T10:09:21.797Z" },
|
||||||
|
{ url = "https://files.pythonhosted.org/packages/15/3a/587f3b177ff1af11d91f5c5ba01acfe9ad4875ab7c72d73b4c2a3b090afe/aemark-0.1.1-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:66727dc7da3da45ae1c0405d9069d0edd6e5c48fce696ea5e327dce46fbcdb3a", size = 769368, upload-time = "2026-06-19T10:09:23.026Z" },
|
||||||
|
{ url = "https://files.pythonhosted.org/packages/d6/cb/9ac41a31e16c66f33bf9366004baeabeab04b0d8f9e2e6867447d6946c74/aemark-0.1.1-cp312-cp312-win32.whl", hash = "sha256:bc4f9e31f97454b70cb0b5b7de25252a59a0e92faef886eda74eb1f65f8c973d", size = 382527, upload-time = "2026-06-19T10:09:24.273Z" },
|
||||||
|
{ url = "https://files.pythonhosted.org/packages/01/bc/c629780bc72973cc1cc3a4ca91720daa8edf37bbc2a2c29ceeea797375ca/aemark-0.1.1-cp312-cp312-win_amd64.whl", hash = "sha256:332b51d6ff927a182d16d4da40930d860abe4a99d99d3219816a5442f7ebecf7", size = 394288, upload-time = "2026-06-19T10:09:25.479Z" },
|
||||||
|
{ url = "https://files.pythonhosted.org/packages/81/9b/6f6238f0d3c09e1472294b24c3938b97db27ff0952c642b7d3ef12ea4f9d/aemark-0.1.1-cp312-cp312-win_arm64.whl", hash = "sha256:28919d11340c54e541fe31fbadd297686c670054bb93e02c5ecd0a5225ce8f8f", size = 382863, upload-time = "2026-06-19T10:09:26.457Z" },
|
||||||
|
{ url = "https://files.pythonhosted.org/packages/af/1f/bebf99bd5eda377347923448115007389952f29e15895208527af00921ef/aemark-0.1.1-cp313-cp313-macosx_10_12_x86_64.whl", hash = "sha256:93a69b7e3be6b00ffcd38be8970c9fe6d99a57844da43fef5205fa834d99fe66", size = 468060, upload-time = "2026-06-19T10:09:27.404Z" },
|
||||||
|
{ url = "https://files.pythonhosted.org/packages/05/c8/24b15087d37128bd7bacada063560d269f6c86ebec58df61ec95b27d78b4/aemark-0.1.1-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:bb9bf8095b4965a1a8566ca5ea2795fc96f035e36bfd9e472bd2ed3718f01dc3", size = 455308, upload-time = "2026-06-19T10:09:28.466Z" },
|
||||||
|
{ url = "https://files.pythonhosted.org/packages/28/33/b1b3e8e2f667f6d6e38112bdf65f32fa19f9d7b8544feb735aba124c1a10/aemark-0.1.1-cp313-cp313-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:4d4d1ab6c2bd01a1ec9018c60a2c35ddc1a3d3e37dbba459cb92087f302eb4f7", size = 544214, upload-time = "2026-06-19T10:09:29.64Z" },
|
||||||
|
{ url = "https://files.pythonhosted.org/packages/27/e7/abcfc081d5562d004bc953b8986f25cf500df625ce9874223659bc36b11e/aemark-0.1.1-cp313-cp313-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:0d296b232d52e795a436b1af211d700903eb6d562567a03d0c79db88188b9936", size = 494722, upload-time = "2026-06-19T10:09:30.974Z" },
|
||||||
|
{ url = "https://files.pythonhosted.org/packages/bb/66/0d00cff512be2e06df7f25e62830644846738db2057253f59affbc572f67/aemark-0.1.1-cp313-cp313-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:aaa6d0b261396b615d45b4ea0b6419625d113cae2d5d0a8e52c08f70494eb943", size = 598196, upload-time = "2026-06-19T10:09:32.044Z" },
|
||||||
|
{ url = "https://files.pythonhosted.org/packages/dd/ae/feacddee57fc9c57bfd9d4ec86f6c6626af3cb4a07220eb527404fc8dcda/aemark-0.1.1-cp313-cp313-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:4bee927e236005b414dcc274d26be867f02a8de96dcd462a0d9c6944c367fbf0", size = 654718, upload-time = "2026-06-19T10:09:33.073Z" },
|
||||||
|
{ url = "https://files.pythonhosted.org/packages/7e/da/00b2bc275c4916a148581dad67914a114554a292964b30ce7c5091251acb/aemark-0.1.1-cp313-cp313-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:0d39be7d7a5658cebde6e89b3723f82946937589af344e200afa9778e3060e1d", size = 516971, upload-time = "2026-06-19T10:09:34.143Z" },
|
||||||
|
{ url = "https://files.pythonhosted.org/packages/e3/7b/c21ae7ee4d3b3f6992f4767953e58db1bd0485fcf7f43fdba47f723d3ebd/aemark-0.1.1-cp313-cp313-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:109315067b14a20e83fde0a5178098731b4f5cd86cd7905f827458946fad1246", size = 518272, upload-time = "2026-06-19T10:09:35.187Z" },
|
||||||
|
{ url = "https://files.pythonhosted.org/packages/69/f8/977f20abc0955b927e60c2b457f3879e3bcde7502054c9b063436e4092b5/aemark-0.1.1-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:512eda328fc5494e76af82b59f270214cc50f171c3e08800e80067e9b345038c", size = 721198, upload-time = "2026-06-19T10:09:36.227Z" },
|
||||||
|
{ url = "https://files.pythonhosted.org/packages/9a/9e/7ee511429869911a8633d6d172cad26030579c43723c2e610453af1ef06d/aemark-0.1.1-cp313-cp313-musllinux_1_2_armv7l.whl", hash = "sha256:2a644c5630de531fc75a5d63b056a95aedbc6ef4e7883cc29327ac951d535faf", size = 771590, upload-time = "2026-06-19T10:09:37.661Z" },
|
||||||
|
{ url = "https://files.pythonhosted.org/packages/6e/90/8b76cfff288bf7aed4173298e453f2add446c8d18abefa3f3abc72924e7f/aemark-0.1.1-cp313-cp313-musllinux_1_2_i686.whl", hash = "sha256:c4122ccfba4d5d3a3cb42e6697051543a26ba7128ab7cd4eb6ed3fe5131d8a22", size = 737238, upload-time = "2026-06-19T10:09:38.861Z" },
|
||||||
|
{ url = "https://files.pythonhosted.org/packages/93/d9/3c06cccc62e2aee921e635a00d595f8550b2c0270472779116a6a9be55ff/aemark-0.1.1-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:1d5f5e22603f97ba2b643426527cb3c19d79463b0bb64fbe03ac2d9e57dc993a", size = 769243, upload-time = "2026-06-19T10:09:40.046Z" },
|
||||||
|
{ url = "https://files.pythonhosted.org/packages/64/2e/8579bf4f4abb1a54195f5f619d4d7d5cd34fe66c7b6ee587d4b5b7c24725/aemark-0.1.1-cp313-cp313-win_amd64.whl", hash = "sha256:e37b06a2cfdab748f280dfc229e37c4c3a82c98b4f49d0d02893a0785c1a8796", size = 394367, upload-time = "2026-06-19T10:09:41.257Z" },
|
||||||
|
{ url = "https://files.pythonhosted.org/packages/0f/08/0678635f86109fffdb847f899b4409e6b99fbf967472efdeff3c57e1674c/aemark-0.1.1-cp313-cp313-win_arm64.whl", hash = "sha256:2993588ec27439cc5adc7917851f9d04ee3c95283f1290fe78379d90fbc25247", size = 383114, upload-time = "2026-06-19T10:09:42.474Z" },
|
||||||
|
{ url = "https://files.pythonhosted.org/packages/38/94/b34c102620515afef1a088ae9a82d4abe332ac3075be375d0be70edc95d5/aemark-0.1.1-cp314-cp314-macosx_10_12_x86_64.whl", hash = "sha256:d0e69cd9da806d2b94ec016544d97a325fcb22477b60c9bf1236521b6978bea1", size = 468275, upload-time = "2026-06-19T10:09:43.686Z" },
|
||||||
|
{ url = "https://files.pythonhosted.org/packages/45/45/c879bb7b354a4e47b8c0b6b20ac95606ccf75512e81c6327487c7a7c2d7a/aemark-0.1.1-cp314-cp314-macosx_11_0_arm64.whl", hash = "sha256:20b902d032885f765ce762fa25dbd59fee9f8aa7b827ecc9f16c58496e01e723", size = 455415, upload-time = "2026-06-19T10:09:44.885Z" },
|
||||||
|
{ url = "https://files.pythonhosted.org/packages/ce/12/b7bc6d238c0a1c22095d6aa960de2a4c53c73ceea725cca0a007ac75c291/aemark-0.1.1-cp314-cp314-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:304667c3a0baa3f7b1cb1170e48cd35001c9aee177af2bf80680f614dd471aeb", size = 543093, upload-time = "2026-06-19T10:09:46.223Z" },
|
||||||
|
{ url = "https://files.pythonhosted.org/packages/f2/fa/09cdf04f9859141a149661d709f4d35bc330a98926513f0002c400dff2da/aemark-0.1.1-cp314-cp314-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:cd161530d9b80640a55fbcfe16289c6e8cb615ae1046ade11e112d3bfa182036", size = 495041, upload-time = "2026-06-19T10:09:47.252Z" },
|
||||||
|
{ url = "https://files.pythonhosted.org/packages/5a/74/7ecbd5a4f5120cbb90ea6e2837a36bfc3cf943a6e17472d36ca91b33c518/aemark-0.1.1-cp314-cp314-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:1ea4b3c171bf1d9feaef1ff12321bf94f9e3eb7db38be8f66b408f1d0959f8b2", size = 597685, upload-time = "2026-06-19T10:09:48.348Z" },
|
||||||
|
{ url = "https://files.pythonhosted.org/packages/29/b4/171ceb88b503fff6740e46c42d1d17f7db861b7e1e56901f74e11a02fb11/aemark-0.1.1-cp314-cp314-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:fd8503d1bc5199e1484311b6d65ee380fd22aeb8ec367651c0e39c4d9f27c87f", size = 654372, upload-time = "2026-06-19T10:09:49.428Z" },
|
||||||
|
{ url = "https://files.pythonhosted.org/packages/3d/2b/ceed2a269503af5912932a233218c184ba464ec0d4b1a389eccdd760e760/aemark-0.1.1-cp314-cp314-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:b3aba427b898c2430bacfe4ded62bef90bb5353b452a1e9d0add6179ca851df4", size = 515791, upload-time = "2026-06-19T10:09:50.546Z" },
|
||||||
|
{ url = "https://files.pythonhosted.org/packages/3e/38/12f9b5107e9afcab320a84d9d46300cad5bfaf2e90a6a3d9cea248adbcdb/aemark-0.1.1-cp314-cp314-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:5d568d8e99ac0730ab5030cf34987eb22e7b9d50e44964233c161e756f527e6c", size = 519423, upload-time = "2026-06-19T10:09:51.634Z" },
|
||||||
|
{ url = "https://files.pythonhosted.org/packages/b0/2d/f8d4fae48934362be4ebcb79b6682d991e823ee8e4de6ef25532307c0d9f/aemark-0.1.1-cp314-cp314-musllinux_1_2_aarch64.whl", hash = "sha256:34530bd2b4e59f6a5e0c4fd715ab34496b0bb5d00b4288b3ee93db43c88a810f", size = 720464, upload-time = "2026-06-19T10:09:52.849Z" },
|
||||||
|
{ url = "https://files.pythonhosted.org/packages/27/2d/db1dc2c2024ac6be28f312aeefb5d1b15b85b2ec329f9cac4bf334b1f358/aemark-0.1.1-cp314-cp314-musllinux_1_2_armv7l.whl", hash = "sha256:faa4b36ad06ebd5f52f49b96ae440330e4220c5343dc69e7b1b92ff30c612089", size = 772108, upload-time = "2026-06-19T10:09:54.157Z" },
|
||||||
|
{ url = "https://files.pythonhosted.org/packages/d9/87/3f2e6b63e3f3b5df70a63bc1d43e213b7b02937447ab6fc94c4ff730a817/aemark-0.1.1-cp314-cp314-musllinux_1_2_i686.whl", hash = "sha256:fffc0c89abde3dbdf506131e1b1416e499e4543031b558d82cc2c0cd0de450ac", size = 737662, upload-time = "2026-06-19T10:09:55.545Z" },
|
||||||
|
{ url = "https://files.pythonhosted.org/packages/05/17/0e033216483a8ae5d0dde9ae8c0f78b464b62aea70aec9ee5a171aef5e68/aemark-0.1.1-cp314-cp314-musllinux_1_2_x86_64.whl", hash = "sha256:0d54c91b7fc7df65553069ea8db6ec8c70c5685735130b177de95b6f436bca81", size = 768312, upload-time = "2026-06-19T10:09:56.803Z" },
|
||||||
|
{ url = "https://files.pythonhosted.org/packages/ff/0b/82fe9178afe8aea4c172a8563694afe3519ea29e04d9ca4ccdf3fabdbc17/aemark-0.1.1-cp314-cp314-win_amd64.whl", hash = "sha256:78c706e546fe8899e7a507820b9d63f8938a64158bbd0d8d344f86daaf15a4d8", size = 391756, upload-time = "2026-06-19T10:09:57.916Z" },
|
||||||
|
{ url = "https://files.pythonhosted.org/packages/21/ca/9eabfb99fddb3a9266336674120fd8df1ae58d5651f584cabd86a806cba6/aemark-0.1.1-cp314-cp314-win_arm64.whl", hash = "sha256:35399ce8ce8e15e8d2d8a8d007c9b8dfc2a92a923493429e8657b046bcafb366", size = 381522, upload-time = "2026-06-19T10:09:59.082Z" },
|
||||||
|
{ url = "https://files.pythonhosted.org/packages/fa/be/dbfad8d80a2f037b769166453b73606e8d6aa672de076717a50fad6a8f22/aemark-0.1.1-cp314-cp314t-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:581fd7dbf57e37e006f23d45e7e401f32c83907a4bb6dee845cab0f586cf9e79", size = 542373, upload-time = "2026-06-19T10:10:00.197Z" },
|
||||||
|
{ url = "https://files.pythonhosted.org/packages/8f/0c/cffd4911980af1391057fd1e12473fc915c3b51c5c543253e6eb325755a3/aemark-0.1.1-cp314-cp314t-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:a804d3ffae6bb6d4673e67536f96df4cf0cd48795ffa75b6d9bbaa469d11382d", size = 494187, upload-time = "2026-06-19T10:10:01.321Z" },
|
||||||
|
{ url = "https://files.pythonhosted.org/packages/75/54/620599105646977be2d3766964a24aa45a35dc5aff4838f6edb3a948aea7/aemark-0.1.1-cp314-cp314t-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:67dcf05f6f9b0ffb73d3f7baeb4ada87d6b5dc26ec56aca3527abfa7916f05df", size = 596882, upload-time = "2026-06-19T10:10:02.384Z" },
|
||||||
|
{ url = "https://files.pythonhosted.org/packages/f2/d8/d0a192801ef68eac915e9157006f4f53a10ed7c0b0b46ac9e372218df9b1/aemark-0.1.1-cp314-cp314t-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:27a61f80c10ee12ca33c4c3e07304f4b84cdb8245ea274b558a970ceb6767817", size = 652553, upload-time = "2026-06-19T10:10:03.668Z" },
|
||||||
|
{ url = "https://files.pythonhosted.org/packages/37/fa/de4969f930ed199d3e395fbff1821a50928ca47567b161b9f21c5eaabcfb/aemark-0.1.1-cp314-cp314t-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:ba20a42edeb94c99c693e54d80c4c4e68f33e53c3e68422499bf3dca6429254a", size = 514859, upload-time = "2026-06-19T10:10:04.8Z" },
|
||||||
|
{ url = "https://files.pythonhosted.org/packages/49/ad/e8db07f9d0a1a3c314e654ab852a1f95074f0aa2c8922a48fa8dc54ce453/aemark-0.1.1-cp314-cp314t-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:201208eb9feb93ed1e7ec1217395ed5292ab80b5b903fbfe71cedd636bb87eea", size = 517850, upload-time = "2026-06-19T10:10:06.047Z" },
|
||||||
|
{ url = "https://files.pythonhosted.org/packages/72/58/8273730c1e1b3bc622bce10d23dc5e1a6309e48de47c13514a4b5fd3d67b/aemark-0.1.1-cp314-cp314t-musllinux_1_2_aarch64.whl", hash = "sha256:813b76ae8668415a58cdf7c78eff2fe0fa1a26725257adf123d715d6ff4a92b1", size = 719901, upload-time = "2026-06-19T10:10:07.423Z" },
|
||||||
|
{ url = "https://files.pythonhosted.org/packages/dc/1f/2d6f5192fd52ced126af5851c7919b574cce36827195a2eb7c6fad38a54d/aemark-0.1.1-cp314-cp314t-musllinux_1_2_armv7l.whl", hash = "sha256:14fec671ca08a4ef55305bfaf267a1671629735f2b281658adf8622280f641e2", size = 770928, upload-time = "2026-06-19T10:10:08.731Z" },
|
||||||
|
{ url = "https://files.pythonhosted.org/packages/49/2f/c0fb323da8d12b18d020949aa15636c97b7ac2cd71ab05b51ad0fbc70af1/aemark-0.1.1-cp314-cp314t-musllinux_1_2_i686.whl", hash = "sha256:24d4c41d58afbda86332f6c1c6cb6ceccfb087428aaa834ad8c95c55920c017c", size = 737035, upload-time = "2026-06-19T10:10:10.016Z" },
|
||||||
|
{ url = "https://files.pythonhosted.org/packages/93/2f/d17b3f892753a6c61f30ff97ba23d32d07bfa758feeddfac9d256d86246e/aemark-0.1.1-cp314-cp314t-musllinux_1_2_x86_64.whl", hash = "sha256:3d4a21593fbf6ce2eb44ed746fc9d98ee2a1c21b5e7d2956c9ffed0a51fa8dca", size = 767584, upload-time = "2026-06-19T10:10:11.21Z" },
|
||||||
|
{ url = "https://files.pythonhosted.org/packages/ec/20/7dd827e7f6548d40737ebe90440f50c0229ea4c4a34f6704573d990877cb/aemark-0.1.1-cp315-cp315-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:f8ef394c8c73956adcd978bf0193cd31fc77bed3f35711c6b222fd2baa870737", size = 515792, upload-time = "2026-06-19T10:10:12.478Z" },
|
||||||
|
{ url = "https://files.pythonhosted.org/packages/ad/49/c93aef2c5e514ecdb4025668ed6fb2e3ae1d274d00e379e2cf8840f8b04c/aemark-0.1.1-cp315-cp315-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:64cc5b3ec2d5b2f95fe9fc2b2b4d50fae55f2aa0c100f809692cd62265ea6007", size = 519595, upload-time = "2026-06-19T10:10:13.517Z" },
|
||||||
|
{ url = "https://files.pythonhosted.org/packages/42/24/a368d11633b6c9a6f74fb14231d638c94ab5704cee83f8cbf10290ff4822/aemark-0.1.1-cp315-cp315t-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:7e4911414cc18d46f3409cb4e138254844a168ae38f86541ebf30d3478df3ceb", size = 514888, upload-time = "2026-06-19T10:10:14.547Z" },
|
||||||
|
{ url = "https://files.pythonhosted.org/packages/89/71/a1112c305a70e59669679a60930104a5a67732264626b906dae8609d89b9/aemark-0.1.1-cp315-cp315t-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:9d39cd7d7772b3c122d346a768542e85116795a1a1886bcf47d0074d636d9eb0", size = 518017, upload-time = "2026-06-19T10:10:15.941Z" },
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "alabaster"
|
name = "alabaster"
|
||||||
version = "1.0.0"
|
version = "1.0.0"
|
||||||
@@ -78,15 +143,15 @@ wheels = [
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "beautifulsoup4"
|
name = "beautifulsoup4"
|
||||||
version = "4.14.3"
|
version = "4.15.0"
|
||||||
source = { registry = "https://pypi.org/simple" }
|
source = { registry = "https://pypi.org/simple" }
|
||||||
dependencies = [
|
dependencies = [
|
||||||
{ name = "soupsieve" },
|
{ name = "soupsieve" },
|
||||||
{ name = "typing-extensions" },
|
{ name = "typing-extensions" },
|
||||||
]
|
]
|
||||||
sdist = { url = "https://files.pythonhosted.org/packages/c3/b0/1c6a16426d389813b48d95e26898aff79abbde42ad353958ad95cc8c9b21/beautifulsoup4-4.14.3.tar.gz", hash = "sha256:6292b1c5186d356bba669ef9f7f051757099565ad9ada5dd630bd9de5fa7fb86", size = 627737, upload-time = "2025-11-30T15:08:26.084Z" }
|
sdist = { url = "https://files.pythonhosted.org/packages/43/65/318323f98dbee45d42dff61d8f047181bc6f2268a9068cfad035a46be5af/beautifulsoup4-4.15.0.tar.gz", hash = "sha256:288e3ca7d54b06f2ac191970bc275c1939cb46d450b255bf6718b04aa37ab4f7", size = 632571, upload-time = "2026-06-07T16:44:20.453Z" }
|
||||||
wheels = [
|
wheels = [
|
||||||
{ url = "https://files.pythonhosted.org/packages/1a/39/47f9197bdd44df24d67ac8893641e16f386c984a0619ef2ee4c51fbbc019/beautifulsoup4-4.14.3-py3-none-any.whl", hash = "sha256:0918bfe44902e6ad8d57732ba310582e98da931428d231a5ecb9e7c703a735bb", size = 107721, upload-time = "2025-11-30T15:08:24.087Z" },
|
{ url = "https://files.pythonhosted.org/packages/88/c6/92fcd42f1ba33e1184263f25bfabf3d27c383410470f169e4b8163bf9c17/beautifulsoup4-4.15.0-py3-none-any.whl", hash = "sha256:d6f88de62e1d4e38ecb1077eb9724cd0eff29d2a08ca16a401e9b9e93f117cf9", size = 109924, upload-time = "2026-06-07T16:44:21.566Z" },
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
@@ -134,11 +199,11 @@ redis = [
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "certifi"
|
name = "certifi"
|
||||||
version = "2026.5.20"
|
version = "2026.6.17"
|
||||||
source = { registry = "https://pypi.org/simple" }
|
source = { registry = "https://pypi.org/simple" }
|
||||||
sdist = { url = "https://files.pythonhosted.org/packages/f3/ce/ee2ecad540810a79593028e88299baeae54d346cc7a0d94b6199988b89b1/certifi-2026.5.20.tar.gz", hash = "sha256:69dea482ab64caa7b9f6aba1c6bf48bb6a5448d1c0f1b17ab42ad8c763a5344d", size = 135422, upload-time = "2026-05-20T11:46:50.073Z" }
|
sdist = { url = "https://files.pythonhosted.org/packages/c9/c7/424b75da314c1045981bd9777432fad05a9e0c69daa4ed7e308bbaffe405/certifi-2026.6.17.tar.gz", hash = "sha256:024c88eeec92ca068db80f02b8b07c9cef7b9fe261d1d535abfd5abd6f6af432", size = 134594, upload-time = "2026-06-17T10:31:07.894Z" }
|
||||||
wheels = [
|
wheels = [
|
||||||
{ url = "https://files.pythonhosted.org/packages/59/8c/57e832b7af6d7c5abe66eb3fbe3a3a32f4d11ea23a1aa7131371035be991/certifi-2026.5.20-py3-none-any.whl", hash = "sha256:3c52e209ba0a4ad7aebe60436a4ab349c39e1e602e8c134221e546902ad25897", size = 134134, upload-time = "2026-05-20T11:46:48.578Z" },
|
{ url = "https://files.pythonhosted.org/packages/ef/2f/c5464532e965badff2f4c4c1a3a83f5697f0d7c407ed0cda44aaa99bb451/certifi-2026.6.17-py3-none-any.whl", hash = "sha256:2227dcbaafe0d2f59279d1762ddddc37783ed4354594f194ffc31d20f41fc3db", size = 133289, upload-time = "2026-06-17T10:31:06.348Z" },
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
@@ -349,86 +414,71 @@ wheels = [
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "coverage"
|
name = "coverage"
|
||||||
version = "7.14.1"
|
version = "7.14.3"
|
||||||
source = { registry = "https://pypi.org/simple" }
|
source = { registry = "https://pypi.org/simple" }
|
||||||
sdist = { url = "https://files.pythonhosted.org/packages/54/fd/0ab2772530e946e1be1abd0bc09e647ec9b02e88f0867857601fefca8953/coverage-7.14.1.tar.gz", hash = "sha256:30c08f7d90415aa98b3c990385dea2939b0da55f38515e5b369b83655f8523be", size = 920132, upload-time = "2026-05-26T20:41:36.783Z" }
|
sdist = { url = "https://files.pythonhosted.org/packages/b4/91/0a7c28934e50d8ac9a7b117712d176f2953c3170bccced5eaacfa3e96175/coverage-7.14.3.tar.gz", hash = "sha256:1a7563a443f3d53fdeb040ec8c9f7466aed7ca3dc5891aa09d3ca3625fa4387f", size = 924398, upload-time = "2026-06-22T23:10:25.584Z" }
|
||||||
wheels = [
|
wheels = [
|
||||||
{ url = "https://files.pythonhosted.org/packages/3d/b7/bdbb725ba02c5b42825b200c940f38b7a54fcad24627b7192f78f8110d76/coverage-7.14.1-cp312-cp312-macosx_10_13_x86_64.whl", hash = "sha256:a06c76364a9360e33d6d23769aefdf7f66f38e2ffb60ceb1baaa4989d83b695c", size = 220022, upload-time = "2026-05-26T20:39:03.702Z" },
|
{ url = "https://files.pythonhosted.org/packages/bd/b0/8a911f6ffe6974dac4df95b468ab9a2899d0e59f0f99a489afeec39f00bc/coverage-7.14.3-cp312-cp312-macosx_10_13_x86_64.whl", hash = "sha256:3d74ff26299c4879ce3a4d826f9d3d4d556fd285fde7bbce3c0ef5a8ab1cec24", size = 220672, upload-time = "2026-06-22T23:08:26.621Z" },
|
||||||
{ url = "https://files.pythonhosted.org/packages/72/81/fdc0898a55c6219223291ec1a1fe89966ef212ce82276aa0899df84b5de0/coverage-7.14.1-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:fad54e871165f6ec2f536063ac74c3104508a12963e64072ba44bd822de52b0c", size = 220379, upload-time = "2026-05-26T20:39:05.381Z" },
|
{ url = "https://files.pythonhosted.org/packages/36/16/0fc0cb52538783dbbae0934b834f5a58fd5354380ee6cad4a07b15dc845d/coverage-7.14.3-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:96150a9cf3468ea20f0bc5d0e21b3df8972c31480ef90fa7614b773cc6429665", size = 221035, upload-time = "2026-06-22T23:08:28.372Z" },
|
||||||
{ url = "https://files.pythonhosted.org/packages/de/72/de048c4a25e13bce59ac6a339351c10bdf2515e07459afcdaf04dc3143a2/coverage-7.14.1-cp312-cp312-manylinux1_i686.manylinux_2_28_i686.manylinux_2_5_i686.whl", hash = "sha256:84b535f00655ecafe1d929d1fb00ed5d6fa3051ea643ab2c161a3887b86f294b", size = 251888, upload-time = "2026-05-26T20:39:07.367Z" },
|
{ url = "https://files.pythonhosted.org/packages/77/e2/421ccfbb48335ac49e93301478cf5d623b0c2bf1c0cadd8e2b2fc6c0c710/coverage-7.14.3-cp312-cp312-manylinux1_i686.manylinux_2_28_i686.manylinux_2_5_i686.whl", hash = "sha256:27d07a46500ba23515b838dbcf52512026af04090755cf6cc64166d88c9b9a1a", size = 252540, upload-time = "2026-06-22T23:08:30.226Z" },
|
||||||
{ url = "https://files.pythonhosted.org/packages/28/30/300c343f68beb9d4cbb64ec81e58c5b6b80b56927f72d2b38654ac26e013/coverage-7.14.1-cp312-cp312-manylinux1_x86_64.manylinux_2_28_x86_64.manylinux_2_5_x86_64.whl", hash = "sha256:6b6b0853b895fe0e98cbfc580d1ec3393d9302b4b1e96a77b3f5c91fdab899e6", size = 254624, upload-time = "2026-05-26T20:39:09.037Z" },
|
{ url = "https://files.pythonhosted.org/packages/06/c2/05b8c890097c61a7f4406b35396b997a635200ded0339eda83dfbe526c5f/coverage-7.14.3-cp312-cp312-manylinux1_x86_64.manylinux_2_28_x86_64.manylinux_2_5_x86_64.whl", hash = "sha256:621e13c6108234d7960aaf5762ab5c3c00f33c30c15af06dcbff0c73bf112727", size = 255274, upload-time = "2026-06-22T23:08:31.876Z" },
|
||||||
{ url = "https://files.pythonhosted.org/packages/b1/ed/7b25642496e8170b6bac14adce00537c6e5fa2d586159401a4de3e8b49e6/coverage-7.14.1-cp312-cp312-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:442cc9c952b2df400cda54bb04ab87330cf2cd08a8692cbbea36773531eb6f37", size = 255739, upload-time = "2026-05-26T20:39:10.889Z" },
|
{ url = "https://files.pythonhosted.org/packages/dc/be/b6d9efe447f8ba3c3c854195f326bd64c54b907d936cd2fdebf8767ec72e/coverage-7.14.3-cp312-cp312-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:4b60ca6d8af70473491a15a343cbabab2e8f9ea66a4376e81c7aa24876a6f977", size = 256389, upload-time = "2026-06-22T23:08:33.843Z" },
|
||||||
{ url = "https://files.pythonhosted.org/packages/7f/a2/abd210b8c4e29c24e4624916db97bb519097a91034aaeb767f937e7da794/coverage-7.14.1-cp312-cp312-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:8270544c361ed405a27a060dbc9ed2c124b084d96dfdc2d9a2510482aef981ad", size = 257998, upload-time = "2026-05-26T20:39:12.722Z" },
|
{ url = "https://files.pythonhosted.org/packages/d4/3c/f26e50acc429e608bc534ac06f0a3c169019c798178ec5e9de3dbc0df9c9/coverage-7.14.3-cp312-cp312-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:c90a7cdd5e380e1ce02f19792e2ac2fbfbf177e35a27e69fd3e873b30d895c0c", size = 258648, upload-time = "2026-06-22T23:08:35.481Z" },
|
||||||
{ url = "https://files.pythonhosted.org/packages/7f/24/7c50beed3792fe62f6ce0545c6686ce83379719e2c0276179333d97eae92/coverage-7.14.1-cp312-cp312-manylinux_2_31_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:48b283b1dd6372e8de2a7a9a4c4d5dc06f4d4fd209b876f3c88a7a205a0c8f84", size = 252296, upload-time = "2026-05-26T20:39:14.259Z" },
|
{ url = "https://files.pythonhosted.org/packages/9e/a2/01c1fabf816c8e1dae197e258edf878a3d3ddc86fbda34b76e5794277d8f/coverage-7.14.3-cp312-cp312-manylinux_2_31_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:5d788e5fd55347eef06ca0732c77d04a264de67e8ff24631270cdff3767a60cf", size = 252949, upload-time = "2026-06-22T23:08:37.562Z" },
|
||||||
{ url = "https://files.pythonhosted.org/packages/15/05/0f874628ebcbfc77ead559ff210281ef06a97db08481832e7dd39274a135/coverage-7.14.1-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:5b0c99ba93a07d56f6df340bb79be53202a082b2fdb81bfe6190b741a3470d54", size = 253658, upload-time = "2026-05-26T20:39:15.923Z" },
|
{ url = "https://files.pythonhosted.org/packages/89/c6/941166dd79c31fd44a13063780ae8d552eee0089a0a0930b9bdb7df554ed/coverage-7.14.3-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:62c7f79db2851c95ef020e5d28b97afde3daf9f7febcd35b53e05638f729063f", size = 254310, upload-time = "2026-06-22T23:08:39.174Z" },
|
||||||
{ url = "https://files.pythonhosted.org/packages/99/6f/ca6ad067364b337ef997802115e7ecad2abd2248b05471464b0dea02b4d4/coverage-7.14.1-cp312-cp312-musllinux_1_2_i686.whl", hash = "sha256:e471bc5769ff073b058cfadb0d736b56ce067c8560eabeb0da88462df98c23e7", size = 251803, upload-time = "2026-05-26T20:39:17.537Z" },
|
{ url = "https://files.pythonhosted.org/packages/10/31/80b1fd028201a961033ce95be3cd1e39e521b3762e6b4a1ac1616cb291e7/coverage-7.14.3-cp312-cp312-musllinux_1_2_i686.whl", hash = "sha256:90f7608aeb5d9b60b523b9fb2a4ee1973867cc4865a3f26fe6c7577073b70205", size = 252453, upload-time = "2026-06-22T23:08:40.84Z" },
|
||||||
{ url = "https://files.pythonhosted.org/packages/c0/30/b9b4d377cd9f40baf228068f5a81faf8450c6228503011bd499708483a50/coverage-7.14.1-cp312-cp312-musllinux_1_2_ppc64le.whl", hash = "sha256:f497a1ea81d4cd7c10ddcaa685135b9aabd291af3d55775a9ddf3cb7a364cdd9", size = 255873, upload-time = "2026-05-26T20:39:19.414Z" },
|
{ url = "https://files.pythonhosted.org/packages/5f/85/c3d9addd94c4b524f3f4af0232075f5fe7170ce99a1386edff803e5934db/coverage-7.14.3-cp312-cp312-musllinux_1_2_ppc64le.whl", hash = "sha256:1e3b91f9c4740aeb571ecf82e5e8d8e4ab62d34fcb5a5d4e5baa38c6f7d2857c", size = 256522, upload-time = "2026-06-22T23:08:42.494Z" },
|
||||||
{ url = "https://files.pythonhosted.org/packages/3c/21/7c721a9e5e6bb88547d30a787aefb97512d3f54c1324c7488d9b3743f7f9/coverage-7.14.1-cp312-cp312-musllinux_1_2_riscv64.whl", hash = "sha256:2222be86d0b54f5dd5a38f45f17f315f737245e857bf0bdedc70734f84a13c02", size = 251372, upload-time = "2026-05-26T20:39:21.169Z" },
|
{ url = "https://files.pythonhosted.org/packages/91/14/e5a0575f73795af3a7a9ae13dadf812e17d32422896839987dc3f86947e1/coverage-7.14.3-cp312-cp312-musllinux_1_2_riscv64.whl", hash = "sha256:c946099774a7699de03cbd0ff0a64e21aed4525eed9d959adde4afe6d15758ef", size = 252023, upload-time = "2026-06-22T23:08:44.243Z" },
|
||||||
{ url = "https://files.pythonhosted.org/packages/9d/8c/f8ae5a2200130e1503cd7661a6cd3b2b7bacef98277fbf3571fb13f8b766/coverage-7.14.1-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:85e85586565842f6932abebd4c18bcb1074223dc0b3576e7d173ca710622813a", size = 253245, upload-time = "2026-05-26T20:39:23.097Z" },
|
{ url = "https://files.pythonhosted.org/packages/38/9b/9652ee531937ce3b8a63a8896885b2b4a2d56adc30e53c9540c666286d88/coverage-7.14.3-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:16b206e521feb8b7133a45754643dead0538489cf8b783b90cf5f4e3299625fd", size = 253893, upload-time = "2026-06-22T23:08:46.113Z" },
|
||||||
{ url = "https://files.pythonhosted.org/packages/34/62/70a9024672a5f6910517d9628c52c9afbdd3cf8f46426af52bb148a56fff/coverage-7.14.1-cp312-cp312-win32.whl", hash = "sha256:4a28fd227808366b196a75476dced2eb35b351d6766ba9c858dc93319e87f4f1", size = 222567, upload-time = "2026-05-26T20:39:24.868Z" },
|
{ url = "https://files.pythonhosted.org/packages/b1/05/42678841c8c38e4b08bdfc48269f5a16dfbf5806000fe6a89b4cece3c691/coverage-7.14.3-cp312-cp312-win32.whl", hash = "sha256:ea3169c7116eb6cdf7608c6c7da9ecfcb3da40688e3a510fac2d1d2bafd6dc35", size = 222734, upload-time = "2026-06-22T23:08:47.858Z" },
|
||||||
{ url = "https://files.pythonhosted.org/packages/f6/81/8b7cd386839b039ebe1855733b9f9449a8dec5d79564018234f185a7fa70/coverage-7.14.1-cp312-cp312-win_amd64.whl", hash = "sha256:54acdb6674a4661768d7bf7db32dfb9f46ab1d764f8aba6df75ce1a6a088724e", size = 223372, upload-time = "2026-05-26T20:39:26.603Z" },
|
{ url = "https://files.pythonhosted.org/packages/df/87/07a4fcee55177a25f1b52331a8e92cf4f2c53b1a9c75ce2981fd59c684ad/coverage-7.14.3-cp312-cp312-win_amd64.whl", hash = "sha256:7ea52fc08f007bcc494d4bb3df3851e95843d881860ba38fe2c64dc100db5e7d", size = 223266, upload-time = "2026-06-22T23:08:49.494Z" },
|
||||||
{ url = "https://files.pythonhosted.org/packages/ae/ba/b44d472022f620d289d95fa830143235c0c36461c6f2437ea8d51e5481ed/coverage-7.14.1-cp312-cp312-win_arm64.whl", hash = "sha256:99cd41ff91afd94896fea3bc002706b6ae4ce95727d06e4a0f39c0a8d8bd8b1a", size = 221989, upload-time = "2026-05-26T20:39:28.242Z" },
|
{ url = "https://files.pythonhosted.org/packages/aa/34/2b8b66a989282ea7b370beb49f50bab29470dc30bb0b03935b6b802782f7/coverage-7.14.3-cp312-cp312-win_arm64.whl", hash = "sha256:8cec0ad652ec57790970d817490105bd917d783c2f7b38d6b58a0ca312e1a336", size = 222655, upload-time = "2026-06-22T23:08:51.766Z" },
|
||||||
{ url = "https://files.pythonhosted.org/packages/8a/9e/5f6d56327c62b185225d145191c607e07515294a0aa6338e58805cd4a5ac/coverage-7.14.1-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:be9f2c802dcfce3f71298303aa5dad0dce440a76c52f2f60dacd8656dab78793", size = 220044, upload-time = "2026-05-26T20:39:29.902Z" },
|
{ url = "https://files.pythonhosted.org/packages/a9/83/7fefbf5df23ed2b7f489907564a7b34b9b07098128e12e0fdfa92626e456/coverage-7.14.3-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:47968988b367990ae4ab17523790c38cd125e02c6bfd379b6022be2d40bdc38c", size = 220699, upload-time = "2026-06-22T23:08:53.522Z" },
|
||||||
{ url = "https://files.pythonhosted.org/packages/75/92/e82aca356744cbbc0f77a0b623e38918c1872361963413a3bab5d0340393/coverage-7.14.1-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:6223a72fd0e4c7156353ec0f08a5f93623e1d3034d0e2683b9bb8ea674131b1d", size = 220412, upload-time = "2026-05-26T20:39:31.561Z" },
|
{ url = "https://files.pythonhosted.org/packages/31/e6/38c3653ff6d56d704b29241362387ca824e38e15b76fdcb7096538195790/coverage-7.14.3-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:0ee68f5c34812780f3a7063382c0a9fcbb99985b7ddcdcaa626e4f3fb2e0783a", size = 221068, upload-time = "2026-06-22T23:08:55.571Z" },
|
||||||
{ url = "https://files.pythonhosted.org/packages/27/c9/385bde0bf7ed0f4bf3a7ee5367060a86b5d218718cfd6fb943c0f836b34f/coverage-7.14.1-cp313-cp313-manylinux1_i686.manylinux_2_28_i686.manylinux_2_5_i686.whl", hash = "sha256:7279d2110a28cebc738b6459ecda2771735a4c18465fbbd36b3288fe5ed92247", size = 251412, upload-time = "2026-05-26T20:39:33.337Z" },
|
{ url = "https://files.pythonhosted.org/packages/20/86/4f5c45d51c5cd10a128933f0fd235393c9146abbfd2ce2dfa68b3267ead3/coverage-7.14.3-cp313-cp313-manylinux1_i686.manylinux_2_28_i686.manylinux_2_5_i686.whl", hash = "sha256:fa9e5c6857a7e80fa22ace5cf3550ae392bbfc322f1d8dd2d2d5a8be38cec027", size = 252060, upload-time = "2026-06-22T23:08:57.464Z" },
|
||||||
{ url = "https://files.pythonhosted.org/packages/51/8c/23faf6a2343a0d17f960a4bd56c43bc7eb4cf312f774dd6ceebd82c7d8fc/coverage-7.14.1-cp313-cp313-manylinux1_x86_64.manylinux_2_28_x86_64.manylinux_2_5_x86_64.whl", hash = "sha256:9eeb3fcbc13ba40dfbdb22d01d196a28e9cef9ed4c29b60061a1e0e823a9929d", size = 254008, upload-time = "2026-05-26T20:39:35.009Z" },
|
{ url = "https://files.pythonhosted.org/packages/82/50/dfce42eff2cecabcd5a9bbad5489449c87db3415f408d23ffee417ce01f6/coverage-7.14.3-cp313-cp313-manylinux1_x86_64.manylinux_2_28_x86_64.manylinux_2_5_x86_64.whl", hash = "sha256:98a0859b0e98e43e1178a9402e19c8127766b14f7109a374d976e5a62c0e5c73", size = 254657, upload-time = "2026-06-22T23:08:59.453Z" },
|
||||||
{ url = "https://files.pythonhosted.org/packages/42/06/36f4aa9ca8a815e6036156e80706a67828bb97bd826948244f6996dda957/coverage-7.14.1-cp313-cp313-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:5f0cfc27c539f07cf5c0a4cfe211d0b6cae039f8f40526dbaa71944e64b50a7b", size = 255241, upload-time = "2026-05-26T20:39:36.71Z" },
|
{ url = "https://files.pythonhosted.org/packages/ba/d2/639ceb1bc8038fd0d66768278d5dc22df3391918b8278c2a21aa2602a531/coverage-7.14.3-cp313-cp313-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:69918344541ed9c8368566c2adc03c0e33d4550d7faa87d1b35e49b6a3286ea9", size = 255892, upload-time = "2026-06-22T23:09:01.291Z" },
|
||||||
{ url = "https://files.pythonhosted.org/packages/ca/79/95266316352f90f6b1c6736bb413302edfde2453fb32422d3911642691b3/coverage-7.14.1-cp313-cp313-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:221c70f316241a78e77e607c227cefc8808d4e08f28d99c04f35694690e940be", size = 257373, upload-time = "2026-05-26T20:39:38.412Z" },
|
{ url = "https://files.pythonhosted.org/packages/8b/96/002094a10e113512500dc1e10430a449417e17b0f90f7d496bcb820208b7/coverage-7.14.3-cp313-cp313-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:b7f300ac92cd4b570724c8ffbbd0c130fee298d2447f41d5a3abf58976fae1de", size = 258026, upload-time = "2026-06-22T23:09:03.017Z" },
|
||||||
{ url = "https://files.pythonhosted.org/packages/e3/9c/58316d1f66c488b5fca8a0eb3e98348807813efa8a0d0833b9021be27488/coverage-7.14.1-cp313-cp313-manylinux_2_31_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:da028256b04ec30e5e0114b6f76172938c313991f0a2d3d894271315cf5d5e43", size = 251635, upload-time = "2026-05-26T20:39:40.268Z" },
|
{ url = "https://files.pythonhosted.org/packages/0b/ec/286a5d2fad9c4bee59bd724feeb7d5bf8303c6c9200b51d1dd945a9c72b0/coverage-7.14.3-cp313-cp313-manylinux_2_31_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:11a7ec9f97ab950f4c5af62229befc7faf208fdbc0116d3902d7e306cf2c5abd", size = 252285, upload-time = "2026-06-22T23:09:04.773Z" },
|
||||||
{ url = "https://files.pythonhosted.org/packages/ef/5a/ca2398a568e16fed7bb713e84ba3603a7164fb65779abe645c565ec890d5/coverage-7.14.1-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:76a085d7005236a767e3426148b2c407e53ad61695c562f8a81da2d373324901", size = 253373, upload-time = "2026-05-26T20:39:42.145Z" },
|
{ url = "https://files.pythonhosted.org/packages/d9/7d/a17753a0b12dd48d0d50f5fab079ad99d3be1eac790494d89f3a417ca0b9/coverage-7.14.3-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:a571bd889cd36c5922ce8e42e059f9d37d02301531d11374afa4c87a578625d5", size = 254023, upload-time = "2026-06-22T23:09:06.513Z" },
|
||||||
{ url = "https://files.pythonhosted.org/packages/6e/2c/0396562c32deaebe7be51d865b3a41e9a87d7561acafe1a28f53b07e019a/coverage-7.14.1-cp313-cp313-musllinux_1_2_i686.whl", hash = "sha256:b553d04b5e778a8e56d57eb134aff42a92718ecba45e79c4764ecfa40efd92ff", size = 251341, upload-time = "2026-05-26T20:39:43.907Z" },
|
{ url = "https://files.pythonhosted.org/packages/86/ef/a76c6ceba6a2c313f905310abf2701d534cada22d372db11731831e9e209/coverage-7.14.3-cp313-cp313-musllinux_1_2_i686.whl", hash = "sha256:de76caefc8deabb0dd1678b6a980be97d14c8d87e213ac194dbf8b09e96d63fb", size = 251989, upload-time = "2026-06-22T23:09:08.382Z" },
|
||||||
{ url = "https://files.pythonhosted.org/packages/fd/8f/a94f9221184c9cae1ee115820e3798e48b6b17777a9f19e46fb9a0c8dc74/coverage-7.14.1-cp313-cp313-musllinux_1_2_ppc64le.whl", hash = "sha256:46f714d2fb8ae2f4f29f23ada7f1e79b759fff5a70f94a1dac23af204c3ec9e4", size = 255497, upload-time = "2026-05-26T20:39:46.166Z" },
|
{ url = "https://files.pythonhosted.org/packages/d9/39/353013a75fec0fb49f7553519f9d52b4441e902e5178c93f38eb6c07cedb/coverage-7.14.3-cp313-cp313-musllinux_1_2_ppc64le.whl", hash = "sha256:d20a15c622194234161535459affa8f7905830391c9ccfa060d495dbfe3a1c7f", size = 256144, upload-time = "2026-06-22T23:09:10.369Z" },
|
||||||
{ url = "https://files.pythonhosted.org/packages/71/69/505d70e47db1eaebcd002c39759707621ef184cd6b1ae084d9f41293f323/coverage-7.14.1-cp313-cp313-musllinux_1_2_riscv64.whl", hash = "sha256:1896f5e19ff3f0431c7ce2172adc54890fd97f86b59ced8ca1649145d9ffe35d", size = 251159, upload-time = "2026-05-26T20:39:48.03Z" },
|
{ url = "https://files.pythonhosted.org/packages/29/0e/613878555d734def11c5b20a2701a15cb3781b9e9ea749da27c5f436e928/coverage-7.14.3-cp313-cp313-musllinux_1_2_riscv64.whl", hash = "sha256:b488bd4b23397db62e7a9459129d01ff06a846582a732efd24834b24a6ada498", size = 251808, upload-time = "2026-06-22T23:09:12.057Z" },
|
||||||
{ url = "https://files.pythonhosted.org/packages/e0/aa/58681c383aa33a9d2ed40a02d7a22fbf780d1fa4d575396365777828198c/coverage-7.14.1-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:62fd185ef9df3c33d1c8178c5af105f762afbad96038de9a4ae100aa6297ca33", size = 252934, upload-time = "2026-05-26T20:39:49.872Z" },
|
{ url = "https://files.pythonhosted.org/packages/af/76/359c058c9cfdcf1e8b107663881225b03b364a320017eda24a2a66e55102/coverage-7.14.3-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:6a3693b4153394d265f44fb855fdc80e72403024d4d6f91c4871b334d028e4e0", size = 253579, upload-time = "2026-06-22T23:09:13.858Z" },
|
||||||
{ url = "https://files.pythonhosted.org/packages/eb/fd/11c928cd6bdffc7074bb5965c173d9ebf517fb00205e1da524b98d29ef92/coverage-7.14.1-cp313-cp313-win32.whl", hash = "sha256:ab4af6352741a604c431c6072fce5bee33bf0f20dc7a56618d6bf6bb89e9810c", size = 222584, upload-time = "2026-05-26T20:39:51.68Z" },
|
{ url = "https://files.pythonhosted.org/packages/1d/d9/4ba2f060933a30ebe363cef9f67a365b0a317e580c0d5d9169d56a73ef1c/coverage-7.14.3-cp313-cp313-win32.whl", hash = "sha256:338b19131ab1a6b767b462bfcbaa692e7ae22f24463e39d49b02a83410ff6b37", size = 222741, upload-time = "2026-06-22T23:09:15.636Z" },
|
||||||
{ url = "https://files.pythonhosted.org/packages/6f/92/fb416fc26d340dcba19518c418d6048e913186e17243982c5e435e41fa7a/coverage-7.14.1-cp313-cp313-win_amd64.whl", hash = "sha256:7af486dabe8954d03b087f0021540897afe084f04e16ff5579e08cc46f871416", size = 223394, upload-time = "2026-05-26T20:39:53.472Z" },
|
{ url = "https://files.pythonhosted.org/packages/76/e8/196ebc25d8f34c06d43a6e9c8513c9266ef8dbf3b5672beb1a00cf5e29fa/coverage-7.14.3-cp313-cp313-win_amd64.whl", hash = "sha256:b3d77f7f196abdef7e01415de1bce09f216189e83e58159cfeef2b92d0464994", size = 223283, upload-time = "2026-06-22T23:09:17.478Z" },
|
||||||
{ url = "https://files.pythonhosted.org/packages/73/c6/02d56e3867972f77d5036de924643f26c056e848f00452cafb4dbc3c29b4/coverage-7.14.1-cp313-cp313-win_arm64.whl", hash = "sha256:2224f89ffd0c5605ccce1ed7a584da162bc7c55f601ab1c946bc9de31a486b42", size = 222015, upload-time = "2026-05-26T20:39:55.374Z" },
|
{ url = "https://files.pythonhosted.org/packages/7c/af/51d2aac6417523a286f10fb25f09eb9518a84df9f1151e93ff6871f34849/coverage-7.14.3-cp313-cp313-win_arm64.whl", hash = "sha256:e6230e688c7c3e65cedd41a774eb4ec221adc6bfee13768231015b702d5e4150", size = 222678, upload-time = "2026-06-22T23:09:19.7Z" },
|
||||||
{ url = "https://files.pythonhosted.org/packages/4d/9e/fcc77914050df73f7662fa1f00902774c79c075a8388ab334074574bf77e/coverage-7.14.1-cp313-cp313t-macosx_10_13_x86_64.whl", hash = "sha256:de286598cc65d2b489411174b1faec2f5a7775fb3201fd925db2a76b4030f37d", size = 220733, upload-time = "2026-05-26T20:39:57.189Z" },
|
{ url = "https://files.pythonhosted.org/packages/61/56/14e3b97facbfa1304dd19e676e26599ad359f04714bed32f7f1c5a88efdc/coverage-7.14.3-cp314-cp314-macosx_10_15_x86_64.whl", hash = "sha256:605ab2b566a22bd94834529d66d295c364aba84afd3e5498285c7a524017b1fc", size = 220741, upload-time = "2026-06-22T23:09:21.616Z" },
|
||||||
{ url = "https://files.pythonhosted.org/packages/f7/67/2963cbdaf5cbadec44efa3a1e39eaa1f02df4079585f05387607a221e126/coverage-7.14.1-cp313-cp313t-macosx_11_0_arm64.whl", hash = "sha256:042c46ded7c288aeb07cf14a28b6c1e10b78fcba40171c3fa1e939377eeef0b5", size = 221086, upload-time = "2026-05-26T20:39:59.019Z" },
|
{ url = "https://files.pythonhosted.org/packages/12/1d/db378b5cca433b90b893f26dab728b280ddd89f272a1fdfed4aeaa05c686/coverage-7.14.3-cp314-cp314-macosx_11_0_arm64.whl", hash = "sha256:a3c2134809e80fac091bfed18a6991b5a5eb5df5ae32b17ac4f4f99864b73dd7", size = 221068, upload-time = "2026-06-22T23:09:23.452Z" },
|
||||||
{ url = "https://files.pythonhosted.org/packages/c8/c5/8701645574e11881f2f47d8930f98bc48b5d43b25eb5b4430dfc4a2f9f48/coverage-7.14.1-cp313-cp313t-manylinux1_i686.manylinux_2_28_i686.manylinux_2_5_i686.whl", hash = "sha256:f4ddbe407477f04c45115d1a4e5bc480f753553b534d338d4c3358b1cdd0ea52", size = 262381, upload-time = "2026-05-26T20:40:00.822Z" },
|
{ url = "https://files.pythonhosted.org/packages/47/f0/3f8421b20d9c4fcd39be9a8ca3c3fda8bc204b44efbd09fede153afd3e2f/coverage-7.14.3-cp314-cp314-manylinux1_i686.manylinux_2_28_i686.manylinux_2_5_i686.whl", hash = "sha256:c02efd507227bde9969cab0db8f48890eb3b5dcad6afac57a4792df4133543ce", size = 252117, upload-time = "2026-06-22T23:09:25.458Z" },
|
||||||
{ url = "https://files.pythonhosted.org/packages/7c/28/7a64d73598263e0c5abd5084211a8474488d31b3c552ff531c719dfcff62/coverage-7.14.1-cp313-cp313t-manylinux1_x86_64.manylinux_2_28_x86_64.manylinux_2_5_x86_64.whl", hash = "sha256:d13e6725992e2d2fd7d81d4f5241952d13740121dfd501da09201be39b2c003a", size = 264458, upload-time = "2026-05-26T20:40:02.506Z" },
|
{ url = "https://files.pythonhosted.org/packages/27/ca/59ea35fb99743549ec8b37eff141ece4431fea590c89e536ed8032ef45cf/coverage-7.14.3-cp314-cp314-manylinux1_x86_64.manylinux_2_28_x86_64.manylinux_2_5_x86_64.whl", hash = "sha256:1bb93c2aa61d2a5b38f1526546d95cf4132cb681e541a337bf8dfd092be816e5", size = 254622, upload-time = "2026-06-22T23:09:27.523Z" },
|
||||||
{ url = "https://files.pythonhosted.org/packages/fa/d8/4969179db9f7eb4df218e69540adf829d1c835f59452513d065d15446802/coverage-7.14.1-cp313-cp313t-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:f747dc8edcfe740130f28f32f3995e955494285717e86ee25af51db2219df08a", size = 266884, upload-time = "2026-05-26T20:40:04.421Z" },
|
{ url = "https://files.pythonhosted.org/packages/c8/25/ec6de51ae7493b92a1cf74d1b763121c29636759167e2a593ba4db5881e4/coverage-7.14.3-cp314-cp314-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:f502e948e03e866538048bba081c075caaa62e5bda6ea5b7432e45f587eb462a", size = 255968, upload-time = "2026-06-22T23:09:29.43Z" },
|
||||||
{ url = "https://files.pythonhosted.org/packages/a6/78/a45d5794dbc9bafd97afc96a4377c86c7820d78b6cf51b89bc1d4e919275/coverage-7.14.1-cp313-cp313t-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:ced2f09ef276fd58611a1ef502164ad266d2b75174e5a40cabbdb4033f9f6cf2", size = 268022, upload-time = "2026-05-26T20:40:06.298Z" },
|
{ url = "https://files.pythonhosted.org/packages/5d/05/c8bfc77823f42b4664fb25842f13b567022f6f84a4c83c8ecbb16734b7cb/coverage-7.14.3-cp314-cp314-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:9973ef2463f8e6cfb61a6324126bb3e17d67a85f22f58d856e583ea2e3ca6501", size = 258284, upload-time = "2026-06-22T23:09:31.397Z" },
|
||||||
{ url = "https://files.pythonhosted.org/packages/21/cb/4f5e354e9e3e67af96bd4e57113e6db6b22298c7168b13eec408a549903d/coverage-7.14.1-cp313-cp313t-manylinux_2_31_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:b84800013769a78ccb9ef4659402e26d06867e337b61ec365f77ad008adea80e", size = 261631, upload-time = "2026-05-26T20:40:08.226Z" },
|
{ url = "https://files.pythonhosted.org/packages/f6/15/1d1b242027124a32b26ef01f82018b8c4ef34ef174aa6aeba7b1eeef48e8/coverage-7.14.3-cp314-cp314-manylinux_2_31_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:9be4e7d4c5ca0427889f8f9d614bd630c2be741b1de7699bca3b2b6c0e41003e", size = 252143, upload-time = "2026-06-22T23:09:33.256Z" },
|
||||||
{ url = "https://files.pythonhosted.org/packages/ec/49/eced49af4cb996d5d8b7e94e736175c513e4facd3398507b89892b4326d8/coverage-7.14.1-cp313-cp313t-musllinux_1_2_aarch64.whl", hash = "sha256:ea8cd6ca0ee9f616aaef3afc6882e32c2cbf18b00d96313ffd76af650574034d", size = 264443, upload-time = "2026-05-26T20:40:10.137Z" },
|
{ url = "https://files.pythonhosted.org/packages/74/b6/d2a9842fd2a5d7d27f1ac851c043a734a494ad75402c5331db3da79ed691/coverage-7.14.3-cp314-cp314-musllinux_1_2_aarch64.whl", hash = "sha256:a574912f3bde4b0619f6e97d01aa590b70998859244793769eb3a6df78ee56d3", size = 253976, upload-time = "2026-06-22T23:09:35.351Z" },
|
||||||
{ url = "https://files.pythonhosted.org/packages/f1/d8/5603a88a7c5913a6b54f6cb1a8c46f7b39cbb30f27cd3f492908da09b2d7/coverage-7.14.1-cp313-cp313t-musllinux_1_2_i686.whl", hash = "sha256:aa5e304a873fabddc11e484e9b6b738bd38bd7bed17b09aa84eecf5332e8b8bb", size = 262069, upload-time = "2026-05-26T20:40:11.999Z" },
|
{ url = "https://files.pythonhosted.org/packages/fd/30/e1600ddf7e226db5558bb5323d2186fff00f505c4b764643ec89ce5d8175/coverage-7.14.3-cp314-cp314-musllinux_1_2_i686.whl", hash = "sha256:e343fb086c9cd780b38622fea7c369acd64c1a0724312149b5d769c387a2b1f5", size = 251942, upload-time = "2026-06-22T23:09:37.313Z" },
|
||||||
{ url = "https://files.pythonhosted.org/packages/f0/59/2ae3cb79da554a06c8619d6c88ea19dd1e4aed4b834b6a83bb1fa243bdc5/coverage-7.14.1-cp313-cp313t-musllinux_1_2_ppc64le.whl", hash = "sha256:5a1c5215be81035e629d5bc756650634d0bf31991038db7a0eccb90f025ce16d", size = 265780, upload-time = "2026-05-26T20:40:13.858Z" },
|
{ url = "https://files.pythonhosted.org/packages/d9/2c/9159de64f9dd648e324328d588a44cfab1e331eb5259ce1141afe2a92dfb/coverage-7.14.3-cp314-cp314-musllinux_1_2_ppc64le.whl", hash = "sha256:3c68df8e61f1e09633fefc7538297145623957a048534368c9d212782aa5e845", size = 256220, upload-time = "2026-06-22T23:09:39.165Z" },
|
||||||
{ url = "https://files.pythonhosted.org/packages/af/5f/b130c1dc999031f2648bd25317fbce505ad8d5562079b4ed81e736a84967/coverage-7.14.1-cp313-cp313t-musllinux_1_2_riscv64.whl", hash = "sha256:79058c47dae6788504b5effb319961bcd72d7240551464b91d474bc0ed186d69", size = 260970, upload-time = "2026-05-26T20:40:16.142Z" },
|
{ url = "https://files.pythonhosted.org/packages/91/67/b7f536cc2c124f48e91b22fbb741d2261f4e3d310faf6f76007f47566e5d/coverage-7.14.3-cp314-cp314-musllinux_1_2_riscv64.whl", hash = "sha256:3e5b550a128419373c2f6cec28a244207013ef15f5cbcff6a5ca09d1dfaaf027", size = 251756, upload-time = "2026-06-22T23:09:41.056Z" },
|
||||||
{ url = "https://files.pythonhosted.org/packages/87/d1/ec13ccddeb48ec963bdfa72a11224bac2584bd045ba13beca82f8113e9c7/coverage-7.14.1-cp313-cp313t-musllinux_1_2_x86_64.whl", hash = "sha256:370c5afae3fa0658e11694a32b24c2778f6bc2d17718121f94ee185e69f26b54", size = 263157, upload-time = "2026-05-26T20:40:18.382Z" },
|
{ url = "https://files.pythonhosted.org/packages/dd/ec/f3718038e2d4860c715a55428377ca7f6c75872caf98cabd982e1d76967d/coverage-7.14.3-cp314-cp314-musllinux_1_2_x86_64.whl", hash = "sha256:2bfc4dd0a912329eccc7484a7d0b2a38032b38c40663b1e1ac595f10c457954b", size = 253413, upload-time = "2026-06-22T23:09:43.306Z" },
|
||||||
{ url = "https://files.pythonhosted.org/packages/cf/c2/cd91ead503045161092d3845f7bb95ea2f25131ce96d3e314dd835d91b9c/coverage-7.14.1-cp313-cp313t-win32.whl", hash = "sha256:3758dd0a7f1fa57365ef2e781df0f0731d38b6e3772259d13dae4bd8a958d4b1", size = 223259, upload-time = "2026-05-26T20:40:20.381Z" },
|
{ url = "https://files.pythonhosted.org/packages/b8/a5/91f11efeef89b3cc9b30461128db15b0511ef813ab889a7b7ab636b3a497/coverage-7.14.3-cp314-cp314-win32.whl", hash = "sha256:0423d64c013057a06e70f070f073cec4b0cbc7d2b27f3c7007292f2ff1d52965", size = 222946, upload-time = "2026-06-22T23:09:45.261Z" },
|
||||||
{ url = "https://files.pythonhosted.org/packages/71/9f/1e28d97e6bd2c76b07f38b7c02870f1371255ff6717f54eca578fcbbdd0e/coverage-7.14.1-cp313-cp313t-win_amd64.whl", hash = "sha256:6ff665fb023a77386fe11685190cee1f60a7d635994a30d9b0a061533d470fce", size = 224320, upload-time = "2026-05-26T20:40:22.316Z" },
|
{ url = "https://files.pythonhosted.org/packages/58/fd/98ac9f524d9ec378de831c034dbdeb544ca7ef7d2d9c9996daf232a037fd/coverage-7.14.3-cp314-cp314-win_amd64.whl", hash = "sha256:92c22e19ce64ca3f2ad751f16f14df1468b4c231bd6af97185063a9c292a0cb3", size = 223436, upload-time = "2026-06-22T23:09:47.177Z" },
|
||||||
{ url = "https://files.pythonhosted.org/packages/a9/e0/d936e908f0e1efa55e52b91e01b52f1055cef5e1ab2718493390ed8e2fb8/coverage-7.14.1-cp313-cp313t-win_arm64.whl", hash = "sha256:17a5a241e5997621a956a7f402a7433ef4221e5152809b785bec79e2323799f1", size = 222577, upload-time = "2026-05-26T20:40:24.894Z" },
|
{ url = "https://files.pythonhosted.org/packages/b4/a0/7cd612d650a772a0ae80144443406bf61981c896c3d57c9e6e79fb2cdbd1/coverage-7.14.3-cp314-cp314-win_arm64.whl", hash = "sha256:41de778bd41780586e2b04912079c73089ab5d839624e28db3bdb26de638da92", size = 222861, upload-time = "2026-06-22T23:09:49.384Z" },
|
||||||
{ url = "https://files.pythonhosted.org/packages/d6/34/fc2f101b151af3799a101f0550b0454aa008afdc0add677394ec4aa8ea10/coverage-7.14.1-cp314-cp314-macosx_10_15_x86_64.whl", hash = "sha256:d5ed429d0b8edaac649e889b4ffcedb6c80b06629a3f93050e3dddfb99235bee", size = 220091, upload-time = "2026-05-26T20:40:27.249Z" },
|
{ url = "https://files.pythonhosted.org/packages/55/57/017353fab573779c0d00448e47d102edd36c792f7b6f233a4d89a7a08384/coverage-7.14.3-cp314-cp314t-macosx_10_15_x86_64.whl", hash = "sha256:8427f370ca67db4c975d2a26acfc0e5783ca0b52444dbc50278ace0f35445949", size = 221474, upload-time = "2026-06-22T23:09:51.417Z" },
|
||||||
{ url = "https://files.pythonhosted.org/packages/3d/a7/1ebae2ab5b961b5c79bb09fe7b3ac99edb190d8be4a8c510b2cf66f46468/coverage-7.14.1-cp314-cp314-macosx_11_0_arm64.whl", hash = "sha256:8011224a62280e50dab346960c03cf47aca1a1e09e608c0fb33fd6e0cc8e9500", size = 220421, upload-time = "2026-05-26T20:40:30.084Z" },
|
{ url = "https://files.pythonhosted.org/packages/69/92/90cf1f1a5c468a9c1b7ba2716e0e205293ad9b02f5f573a6de4318b15ba1/coverage-7.14.3-cp314-cp314t-macosx_11_0_arm64.whl", hash = "sha256:d8e88f335544a47e22ae2e45b344772925ec65166555c958720d5ed971880891", size = 221738, upload-time = "2026-06-22T23:09:53.487Z" },
|
||||||
{ url = "https://files.pythonhosted.org/packages/5e/90/92aca9cf0acc95123c96cd1eb1f08917897a7f5dee01e15738922971ec31/coverage-7.14.1-cp314-cp314-manylinux1_i686.manylinux_2_28_i686.manylinux_2_5_i686.whl", hash = "sha256:12c42ec1e14f553c4f817e989365982e646e27211f10a0f717855b94a79c8906", size = 251466, upload-time = "2026-05-26T20:40:32.542Z" },
|
{ url = "https://files.pythonhosted.org/packages/a4/c0/4df964fa539f8399fd7679c09c472d73744de334686fd3f01e3a2465ce4e/coverage-7.14.3-cp314-cp314t-manylinux1_i686.manylinux_2_28_i686.manylinux_2_5_i686.whl", hash = "sha256:beaab199b9e5ceaf5a225e16a9d4df136f2a1eae0a5c20de1e277c8a5225f388", size = 263101, upload-time = "2026-06-22T23:09:55.895Z" },
|
||||||
{ url = "https://files.pythonhosted.org/packages/26/2b/78048cbe3b999f6cbf9cc0d90abba6a88a3e0863a8c1c6cbc762f3f8802f/coverage-7.14.1-cp314-cp314-manylinux1_x86_64.manylinux_2_28_x86_64.manylinux_2_5_x86_64.whl", hash = "sha256:06144cd511cf2624873a035c5069cf297144f6e77a73ee3d7a55b605ec5efb42", size = 253973, upload-time = "2026-05-26T20:40:34.473Z" },
|
{ url = "https://files.pythonhosted.org/packages/06/76/e5d33b2576ae3bf2be2058cd1cae57774b61e400f2c3c58f3783dc2ffb4a/coverage-7.14.3-cp314-cp314t-manylinux1_x86_64.manylinux_2_28_x86_64.manylinux_2_5_x86_64.whl", hash = "sha256:b3ff255799f5a1676c71c1c32ec01fd043aa09d57b3d95764b24992757184784", size = 265225, upload-time = "2026-06-22T23:09:57.904Z" },
|
||||||
{ url = "https://files.pythonhosted.org/packages/8e/21/c2e33b29d1cfde484a19d437afc343c6cd30b08d78cbbf9f5aff14e57b2b/coverage-7.14.1-cp314-cp314-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:a311d8e1da24be5c1ccf85cbfb06315dbaa1703d5a1eab3f6432c72b837917c8", size = 255318, upload-time = "2026-05-26T20:40:38.154Z" },
|
{ url = "https://files.pythonhosted.org/packages/61/d2/e52419afe391a39ba27fdefaf0737d8e34bf03faef6ab3b3006545bbd0d0/coverage-7.14.3-cp314-cp314t-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:878832eaac515b62decfa76965aed558775f86bf1fc8cca76993c0c84ae31aed", size = 267643, upload-time = "2026-06-22T23:09:59.938Z" },
|
||||||
{ url = "https://files.pythonhosted.org/packages/8e/ee/aad2f108d63b769121005302f16bf66db8625c88ceaba466942e09a2607e/coverage-7.14.1-cp314-cp314-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:c79cead5b5bc584d9c71451cb984d0e3a84e0c0937379c8efcbf27c8d661b851", size = 257633, upload-time = "2026-05-26T20:40:40.164Z" },
|
{ url = "https://files.pythonhosted.org/packages/58/7a/f2625d8d5006b6b20fba5afaef00b24a763fe96476ea798a3076cbc1f84e/coverage-7.14.3-cp314-cp314t-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:611e62cb9386096d81b63e0a05330750268617231e7bd598e1fe77482a2c58a5", size = 268762, upload-time = "2026-06-22T23:10:01.943Z" },
|
||||||
{ url = "https://files.pythonhosted.org/packages/c2/f8/11a2c29b4fd76d9849f81d0bb812ec0017a9396df3217214e38934a8c837/coverage-7.14.1-cp314-cp314-manylinux_2_31_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:dcbf65f1f66a26cdd88c35cf68fb4729c5d1cd2e88added72420541dfb212034", size = 251488, upload-time = "2026-05-26T20:40:42.631Z" },
|
{ url = "https://files.pythonhosted.org/packages/7d/bf/908024006bba57127354d74e938954b9c3cd765cc2e0412dc9c37b415cda/coverage-7.14.3-cp314-cp314t-manylinux_2_31_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:02c41de2a88011b893050fc9830267d927a50a215f7ad5ec17349db7090ccf26", size = 262208, upload-time = "2026-06-22T23:10:03.954Z" },
|
||||||
{ url = "https://files.pythonhosted.org/packages/c9/b8/9a5820de4b8ac2b71d85e3b5fb49108d7469c665f0e2ad0dd7569023e305/coverage-7.14.1-cp314-cp314-musllinux_1_2_aarch64.whl", hash = "sha256:fd86572566fb40189a8260446158235159bc7a82dfbc87a3b39cf4fb57fcec1c", size = 253329, upload-time = "2026-05-26T20:40:45.208Z" },
|
{ url = "https://files.pythonhosted.org/packages/34/a0/d4f9296441b909817442fdb26bd77a698f08272ec683a7394b00eb2e47a0/coverage-7.14.3-cp314-cp314t-musllinux_1_2_aarch64.whl", hash = "sha256:526ce9721116af23b1065089f0b75046fe521e7772ab94b641cd66b7a0421889", size = 265096, upload-time = "2026-06-22T23:10:05.936Z" },
|
||||||
{ url = "https://files.pythonhosted.org/packages/6b/ff/f33e4823667e27548e8fd8df44217515303f9808d0ff29817db56f87d990/coverage-7.14.1-cp314-cp314-musllinux_1_2_i686.whl", hash = "sha256:7771b601718fdde84832c3a434ca9bbf4ae9adbc49d84198b4110700c3c77c36", size = 251291, upload-time = "2026-05-26T20:40:47.502Z" },
|
{ url = "https://files.pythonhosted.org/packages/e8/da/4ae4f3f4e477b56a4ce1e5c48a35eff38a94b50130ce5bdc897024741cfc/coverage-7.14.3-cp314-cp314t-musllinux_1_2_i686.whl", hash = "sha256:e4ed44705ca4bead6fc977a8b741f2145608289b33c8a9b42a95d0f15aedbf4d", size = 262699, upload-time = "2026-06-22T23:10:07.973Z" },
|
||||||
{ url = "https://files.pythonhosted.org/packages/68/9b/489db0ebb209054766b90a9014a45f6d26eb724c02ec21311c3733b5a644/coverage-7.14.1-cp314-cp314-musllinux_1_2_ppc64le.whl", hash = "sha256:39b21e212c55af06fa375e3dbf90a8a8e38792f3a910c580066d23563830ddd5", size = 255564, upload-time = "2026-05-26T20:40:49.372Z" },
|
{ url = "https://files.pythonhosted.org/packages/d8/7a/6927148073ff32856d78baa77b4ddc07a9be7e90020f9db0661c4ca523a1/coverage-7.14.3-cp314-cp314t-musllinux_1_2_ppc64le.whl", hash = "sha256:2415902f385a23dcc4ccd26e0ba803249a169af6a930c003a4c715eeb9a5444e", size = 266433, upload-time = "2026-06-22T23:10:10.145Z" },
|
||||||
{ url = "https://files.pythonhosted.org/packages/27/b5/16bc2d4c2409b23c7737edb68c83bc89e345f378050549fe1d75ac7d34d5/coverage-7.14.1-cp314-cp314-musllinux_1_2_riscv64.whl", hash = "sha256:f2302660e32562a532b442480121aef8aa61a5bdb20b30bf0adab29f10a5a4b4", size = 251107, upload-time = "2026-05-26T20:40:51.677Z" },
|
{ url = "https://files.pythonhosted.org/packages/f7/a7/774f658dbe9c4c3f5daa86a87e0459ac3832e4e3cc67affe078547f727b9/coverage-7.14.3-cp314-cp314t-musllinux_1_2_riscv64.whl", hash = "sha256:b75ee850fc2d7c831e883220c445b035f2224de2ba6103f1e56dbd237ab913f7", size = 261547, upload-time = "2026-06-22T23:10:12.191Z" },
|
||||||
{ url = "https://files.pythonhosted.org/packages/7d/0c/2629997469a00cd069d588a41c9dc887610f2775ae89d250c4791e65272a/coverage-7.14.1-cp314-cp314-musllinux_1_2_x86_64.whl", hash = "sha256:03a6f93c1ec3b7f2e77b5dbcc5573a2c21f12529a5c6bbe0f16f72303cc2fa4d", size = 252764, upload-time = "2026-05-26T20:40:54.267Z" },
|
{ url = "https://files.pythonhosted.org/packages/3d/14/a0c18c0376c43cbf973f43ef6ca20019c950597180e6396232f7b6a27102/coverage-7.14.3-cp314-cp314t-musllinux_1_2_x86_64.whl", hash = "sha256:dc9b4e35e7c3920e925ba7f14886fd5fbe481232754624e832ddba66c7535635", size = 263859, upload-time = "2026-06-22T23:10:14.492Z" },
|
||||||
{ url = "https://files.pythonhosted.org/packages/d2/ee/f78d63c8f079e0d7211c7e2401fa17e311514534ba61bae03e4b287ce4ab/coverage-7.14.1-cp314-cp314-win32.whl", hash = "sha256:8a3ce026d73290f42f08dafecbd82c193a74df280461fbf97300fec51fd133ee", size = 222837, upload-time = "2026-05-26T20:40:56.496Z" },
|
{ url = "https://files.pythonhosted.org/packages/10/ac/43a3d0f460af524b131a6191805bc5d18b806ab4e828fbf82e8c8c3af446/coverage-7.14.3-cp314-cp314t-win32.whl", hash = "sha256:7b27c822a8161afbe48e99f1adfb098d270ae7e0f7d7b0555ce110529bdb69cc", size = 223250, upload-time = "2026-06-22T23:10:16.758Z" },
|
||||||
{ url = "https://files.pythonhosted.org/packages/dc/b9/be539854f93a70dfbeec69117f33ec70dc42ff0b65b5b07ab8d40d04228e/coverage-7.14.1-cp314-cp314-win_amd64.whl", hash = "sha256:114c95ef29302423b87d159075805f4ab973254a2638a5d7d046c94887cc87d7", size = 223650, upload-time = "2026-05-26T20:40:58.351Z" },
|
{ url = "https://files.pythonhosted.org/packages/3f/5f/d5e5c56b0712e96ce8f69fe7dbf229ff938b437bc50862743c8a0d2cea84/coverage-7.14.3-cp314-cp314t-win_amd64.whl", hash = "sha256:39e1dbbb6ff2c338e0196a482558a792a1de3aa64261196f5cdb3da016ad9cda", size = 224082, upload-time = "2026-06-22T23:10:19.23Z" },
|
||||||
{ url = "https://files.pythonhosted.org/packages/fe/9e/24e2842fef40f35ac82ba3a7719c8023d011bf3bf652d0675316a9d088a1/coverage-7.14.1-cp314-cp314-win_arm64.whl", hash = "sha256:a07891c3f4805442b31b71e84ba3cf29ed1aa9a428284e06deeb4b23e5b46343", size = 222218, upload-time = "2026-05-26T20:41:00.321Z" },
|
{ url = "https://files.pythonhosted.org/packages/62/35/947cbd5be1d3bcbbdc43d6791de8a56c6501903311d42915ae06a82815f0/coverage-7.14.3-cp314-cp314t-win_arm64.whl", hash = "sha256:68520c90babfa2d560eca6d497921ed3a4f469623bd709733124491b2aa8ef3f", size = 223400, upload-time = "2026-06-22T23:10:21.24Z" },
|
||||||
{ url = "https://files.pythonhosted.org/packages/0a/1d/ac0a9df5fe31c1e8bdd658074905fc12844a05c1a7e3fdb8417e97c31e23/coverage-7.14.1-cp314-cp314t-macosx_10_15_x86_64.whl", hash = "sha256:1101a5ebb083aecb625ebb6209d4105b58f647b093cb2dc8122d7b33f743cfe1", size = 220822, upload-time = "2026-05-26T20:41:02.281Z" },
|
{ url = "https://files.pythonhosted.org/packages/eb/e3/a0aa32bfa3a081951f60a23bc0e7b512891ef0eecda1153cf1d8ba36c6b1/coverage-7.14.3-py3-none-any.whl", hash = "sha256:fb7e18afb6e903c1a92401a2f0501ac277dca527bb9ca6fe1f691a8a0026a0e8", size = 212469, upload-time = "2026-06-22T23:10:23.405Z" },
|
||||||
{ url = "https://files.pythonhosted.org/packages/32/cf/f964fd9aff20323f9f1a726c97135f8a76bcd87b92dad141a456a43f3c64/coverage-7.14.1-cp314-cp314t-macosx_11_0_arm64.whl", hash = "sha256:851b9e1e4e8a4608e77c79714b2e77c0970d2ed7202a05e92ae407817481887b", size = 221084, upload-time = "2026-05-26T20:41:04.593Z" },
|
|
||||||
{ url = "https://files.pythonhosted.org/packages/d8/5e/7e5ef2aba844de2b80d678619fcf0841b42e3f37f16411226f3fe4c1016f/coverage-7.14.1-cp314-cp314t-manylinux1_i686.manylinux_2_28_i686.manylinux_2_5_i686.whl", hash = "sha256:d5b89cdfb2ee051b71e8c3c70bd81a9eff81100f736a269136fe1a68efe00474", size = 262454, upload-time = "2026-05-26T20:41:06.641Z" },
|
|
||||||
{ url = "https://files.pythonhosted.org/packages/64/62/75809bded87015cc4935524218a2a8ed8dd1a8498bfed30a2f4f7a4b4d34/coverage-7.14.1-cp314-cp314t-manylinux1_x86_64.manylinux_2_28_x86_64.manylinux_2_5_x86_64.whl", hash = "sha256:0177614a0370f227888b4e436a7c55686d6a9f90eb1ade2b624ba685a1686e86", size = 264578, upload-time = "2026-05-26T20:41:08.556Z" },
|
|
||||||
{ url = "https://files.pythonhosted.org/packages/f3/42/d33392dc14633525012d2d504fa1a33b05538bf535f5c1d64675e5754b78/coverage-7.14.1-cp314-cp314t-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:2d69af5dea2de76fc485a83032a630523f985198b7e25be901ec60181587b01e", size = 266981, upload-time = "2026-05-26T20:41:10.824Z" },
|
|
||||||
{ url = "https://files.pythonhosted.org/packages/2a/49/0157c4428c2aca7f1e09d5565930586fd5ae36f1655f08b0daa7cf1fcae1/coverage-7.14.1-cp314-cp314t-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:35ab22d91de736e8966b980dc355cbcdd2c6dbbcfe275f9a2991bc8a91b3df65", size = 268112, upload-time = "2026-05-26T20:41:12.966Z" },
|
|
||||||
{ url = "https://files.pythonhosted.org/packages/96/26/86b9ce71f4092b1ed325ce1421698081df1286b833400b6836912834d6e0/coverage-7.14.1-cp314-cp314t-manylinux_2_31_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:357d4e32935c36588aaba057d734fa32428c360c9fc2e4442afbf1b646beee6e", size = 261558, upload-time = "2026-05-26T20:41:15Z" },
|
|
||||||
{ url = "https://files.pythonhosted.org/packages/20/4c/c311210c5472cf5401d8422b0d7812cdd520f24417673afabda6c323faca/coverage-7.14.1-cp314-cp314t-musllinux_1_2_aarch64.whl", hash = "sha256:51bd64741cc6fa065abd300ede1afe5a5291ece9c31da8b24884deda48bcc3f8", size = 264447, upload-time = "2026-05-26T20:41:17.369Z" },
|
|
||||||
{ url = "https://files.pythonhosted.org/packages/fb/71/59513f8710ed3e6b0ac0a050a5b7e977bb9c9e880354863b5d00d8809256/coverage-7.14.1-cp314-cp314t-musllinux_1_2_i686.whl", hash = "sha256:9132cd363a68a4c3daa7c8704a654b1e39d3360f6f5b8ddd470608a945236c07", size = 262048, upload-time = "2026-05-26T20:41:19.309Z" },
|
|
||||||
{ url = "https://files.pythonhosted.org/packages/84/8d/bceed32dc494f5bbf50f775cd2e78ca814953942b5ea28d3c1c3ac316f14/coverage-7.14.1-cp314-cp314t-musllinux_1_2_ppc64le.whl", hash = "sha256:07c6290b1697b862c0478eab545eec949a0d0e4d6d03497f446d706da3b4f2de", size = 265781, upload-time = "2026-05-26T20:41:21.559Z" },
|
|
||||||
{ url = "https://files.pythonhosted.org/packages/e7/c5/9348fe40dbfd4991aaf78df2c6c3098bfb2cc834d1fd362a64b4efef855a/coverage-7.14.1-cp314-cp314t-musllinux_1_2_riscv64.whl", hash = "sha256:5ea0c297e27133853b4d8a3eb799bff5a2dbd9f2f41537a240d337ac9b4df890", size = 260896, upload-time = "2026-05-26T20:41:23.428Z" },
|
|
||||||
{ url = "https://files.pythonhosted.org/packages/ca/92/1ea0f03929da7cf87206b1fa24f4c8e9c158be0455481af29ec0a1f3503f/coverage-7.14.1-cp314-cp314t-musllinux_1_2_x86_64.whl", hash = "sha256:01b7733daad0237daa01ef80fe2dfceffc911e6a17fa7b55d14aa8214eaaaecd", size = 263214, upload-time = "2026-05-26T20:41:25.419Z" },
|
|
||||||
{ url = "https://files.pythonhosted.org/packages/f6/a9/b2493c054c0e01a643266742ab45e15744e60743f9260cd930c7142b1124/coverage-7.14.1-cp314-cp314t-win32.whl", hash = "sha256:6adc5a36984624a70bf11d7184e20fa0a49aa7c47ffab43804106a1a695ea22e", size = 223624, upload-time = "2026-05-26T20:41:27.795Z" },
|
|
||||||
{ url = "https://files.pythonhosted.org/packages/fc/bd/3e1e6a57fccd2d7c83fcdf338e93ba98eb85c6e877dd34731ac585375490/coverage-7.14.1-cp314-cp314t-win_amd64.whl", hash = "sha256:ddf799247318f34dbcd2efa8c95a8d0642674e926bb1774cf9b63dfd2a389d1c", size = 224728, upload-time = "2026-05-26T20:41:30.098Z" },
|
|
||||||
{ url = "https://files.pythonhosted.org/packages/bb/d7/31066cf1d2f0c6c797fce911bcfa01dd35642dc6da992a950256097c5860/coverage-7.14.1-cp314-cp314t-win_arm64.whl", hash = "sha256:145986fe66647eb489f18d9a997567a3fd358584c4b5a808769113abc07466af", size = 222752, upload-time = "2026-05-26T20:41:32.123Z" },
|
|
||||||
{ url = "https://files.pythonhosted.org/packages/8a/3c/1a983b9a745d7f83d53f057bcc5bf79ba6a2bbc08266b3f0c7d6fe630c9b/coverage-7.14.1-py3-none-any.whl", hash = "sha256:a252f21c27e38347e60111a3266b03827422a7d5525951aceee313aa68bab1d2", size = 211815, upload-time = "2026-05-26T20:41:34.078Z" },
|
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
@@ -442,55 +492,52 @@ wheels = [
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "cryptography"
|
name = "cryptography"
|
||||||
version = "48.0.0"
|
version = "49.0.0"
|
||||||
source = { registry = "https://pypi.org/simple" }
|
source = { registry = "https://pypi.org/simple" }
|
||||||
dependencies = [
|
dependencies = [
|
||||||
{ name = "cffi", marker = "platform_python_implementation != 'PyPy'" },
|
{ name = "cffi", marker = "platform_python_implementation != 'PyPy'" },
|
||||||
]
|
]
|
||||||
sdist = { url = "https://files.pythonhosted.org/packages/9f/a9/db8f313fdcd85d767d4973515e1db101f9c71f95fced83233de224673757/cryptography-48.0.0.tar.gz", hash = "sha256:5c3932f4436d1cccb036cb0eaef46e6e2db91035166f1ad6505c3c9d5a635920", size = 832984, upload-time = "2026-05-04T22:59:38.133Z" }
|
sdist = { url = "https://files.pythonhosted.org/packages/1f/99/d1c90d6041656cc6ee229dc99cd67fd0cd5aec3c5f7d72fffc27cc750054/cryptography-49.0.0.tar.gz", hash = "sha256:f89660a348f4f78a92366240a61404e337586ef7f5909a2fef59ca88ef505493", size = 854345, upload-time = "2026-06-12T20:02:30.512Z" }
|
||||||
wheels = [
|
wheels = [
|
||||||
{ url = "https://files.pythonhosted.org/packages/df/3d/01f6dd9190170a5a241e0e98c2d04be3664a9e6f5b9b872cde63aff1c3dd/cryptography-48.0.0-cp311-abi3-macosx_10_9_universal2.whl", hash = "sha256:0c558d2cdffd8f4bbb30fc7134c74d2ca9a476f830bb053074498fbc86f41ed6", size = 8001587, upload-time = "2026-05-04T22:57:36.803Z" },
|
{ url = "https://files.pythonhosted.org/packages/9b/22/adf66990e63584a68dfb50c24f48a125c07b1699899381c8151e63ed458c/cryptography-49.0.0-cp311-abi3-macosx_11_0_arm64.whl", hash = "sha256:966fe0e9c67490071f14c0d2b1cb2dfb3023c5ce39457343931415f08382f2db", size = 4032100, upload-time = "2026-06-12T20:02:32.143Z" },
|
||||||
{ url = "https://files.pythonhosted.org/packages/b2/6e/e90527eef33f309beb811cf7c982c3aeffcce8e3edb178baa4ca3ae4a6fa/cryptography-48.0.0-cp311-abi3-manylinux2014_aarch64.manylinux_2_17_aarch64.whl", hash = "sha256:f5333311663ea94f75dd408665686aaf426563556bb5283554a3539177e03b8c", size = 4690433, upload-time = "2026-05-04T22:57:40.373Z" },
|
{ url = "https://files.pythonhosted.org/packages/09/41/3797cfaf69cae04a13ee78ebd83f0678d9c02b4779d21ce24445326f1a69/cryptography-49.0.0-cp311-abi3-manylinux2014_aarch64.manylinux_2_17_aarch64.whl", hash = "sha256:36d1709f992593689b45bda411498d62c6e365f2ca00b84657d4dadd24de16db", size = 4692978, upload-time = "2026-06-12T20:01:21.305Z" },
|
||||||
{ url = "https://files.pythonhosted.org/packages/90/04/673510ed51ddff56575f306cf1617d80411ee76831ccd3097599140efdfe/cryptography-48.0.0-cp311-abi3-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:7995ef305d7165c3f11ae07f2517e5a4f1d5c18da1376a0a9ed496336b69e5f3", size = 4710620, upload-time = "2026-05-04T22:57:42.935Z" },
|
{ url = "https://files.pythonhosted.org/packages/e6/8b/43011f7ebe515a8aa20d61f290a326cd890c2e738e16e59eaff8d9c3a412/cryptography-49.0.0-cp311-abi3-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:0e959b578856a3924bc0cbb710fc12c387b9412a951389f3ca61704a9e25f325", size = 4716422, upload-time = "2026-06-12T20:01:48.566Z" },
|
||||||
{ url = "https://files.pythonhosted.org/packages/14/d5/e9c4ef932c8d800490c34d8bd589d64a31d5890e27ec9e9ad532be893294/cryptography-48.0.0-cp311-abi3-manylinux_2_28_aarch64.whl", hash = "sha256:40ba1f85eaa6959837b1d51c9767e230e14612eea4ef110ee8854ada22da1bf5", size = 4696283, upload-time = "2026-05-04T22:57:45.294Z" },
|
{ url = "https://files.pythonhosted.org/packages/4a/91/01ce7303a4579e6d3a6abef01bd322848e9ea7a219adcabc5048b9033571/cryptography-49.0.0-cp311-abi3-manylinux_2_28_aarch64.whl", hash = "sha256:53ecee2e23f7169b6117e99fc8a944e5e50f79e69758a83b52a00cb98ab2b2d2", size = 4700503, upload-time = "2026-06-12T20:02:47.091Z" },
|
||||||
{ url = "https://files.pythonhosted.org/packages/0c/29/174b9dfb60b12d59ecfc6cfa04bc88c21b42a54f01b8aae09bb6e51e4c7f/cryptography-48.0.0-cp311-abi3-manylinux_2_28_ppc64le.whl", hash = "sha256:369a6348999f94bbd53435c894377b20ab95f25a9065c283570e70150d8abc3c", size = 5296573, upload-time = "2026-05-04T22:57:47.933Z" },
|
{ url = "https://files.pythonhosted.org/packages/62/99/a2c95cf8293f07491e9e27c20cc4dcd18176d944e674679adeb1d0173fd6/cryptography-49.0.0-cp311-abi3-manylinux_2_28_ppc64le.whl", hash = "sha256:2eda353d8a27bcbcaa4cbed18994a74ab4d19a2ca897db188ea269ab9b71419b", size = 5309779, upload-time = "2026-06-12T20:02:08.987Z" },
|
||||||
{ url = "https://files.pythonhosted.org/packages/95/38/0d29a6fd7d0d1373f0c0c88a04ba20e359b257753ac497564cd660fc1d55/cryptography-48.0.0-cp311-abi3-manylinux_2_28_x86_64.whl", hash = "sha256:a0e692c683f4df67815a2d258b324e66f4738bd7a96a218c826dce4f4bd05d8f", size = 4743677, upload-time = "2026-05-04T22:57:50.067Z" },
|
{ url = "https://files.pythonhosted.org/packages/20/2c/0622f20ff02b2ef32558733443805dc82fd4c275be01b2d19d14676f3a1b/cryptography-49.0.0-cp311-abi3-manylinux_2_28_x86_64.whl", hash = "sha256:2afe9051da7ae7bd5905da5a949280c7d2bb75682e188f650a9d0f2756b834c6", size = 4749683, upload-time = "2026-06-12T20:02:03.335Z" },
|
||||||
{ url = "https://files.pythonhosted.org/packages/30/be/eef653013d5c63b6a490529e0316f9ac14a37602965d4903efed1399f32b/cryptography-48.0.0-cp311-abi3-manylinux_2_31_armv7l.whl", hash = "sha256:18349bbc56f4743c8b12dc32e2bccb2cf83ee8b69a3bba74ef8ae857e26b3d25", size = 4330808, upload-time = "2026-05-04T22:57:52.301Z" },
|
{ url = "https://files.pythonhosted.org/packages/a3/5b/c5246635d5fd3b64e0d45ae10e99fd32fe9676a79915ccfe5a61ba9af1a5/cryptography-49.0.0-cp311-abi3-manylinux_2_31_armv7l.whl", hash = "sha256:0b82e28ee398a386f0807bba7884d30f25218855690f45115831bcce5d90822c", size = 4337874, upload-time = "2026-06-12T20:02:54.323Z" },
|
||||||
{ url = "https://files.pythonhosted.org/packages/84/9e/500463e87abb7a0a0f9f256ec21123ecde0a7b5541a15e840ea54551fd81/cryptography-48.0.0-cp311-abi3-manylinux_2_34_aarch64.whl", hash = "sha256:7e8eac43dfca5c4cccc6dad9a80504436fca53bb9bc3100a2386d730fbe6b602", size = 4695941, upload-time = "2026-05-04T22:57:54.603Z" },
|
{ url = "https://files.pythonhosted.org/packages/6d/88/05563c7fe2e914e87d1a536d06fe83e66b4e1d95cb593e05aea375531da8/cryptography-49.0.0-cp311-abi3-manylinux_2_34_aarch64.whl", hash = "sha256:ccac2bfebc306b862133e3bb71f3f6ee8bb525240089b2d952e4144b3a6d5da7", size = 4700283, upload-time = "2026-06-12T20:01:34.822Z" },
|
||||||
{ url = "https://files.pythonhosted.org/packages/e3/dc/7303087450c2ec9e7fbb750e17c2abfbc658f23cbd0e54009509b7cc4091/cryptography-48.0.0-cp311-abi3-manylinux_2_34_ppc64le.whl", hash = "sha256:9ccdac7d40688ecb5a3b4a604b8a88c8002e3442d6c60aead1db2a89a041560c", size = 5252579, upload-time = "2026-05-04T22:57:57.207Z" },
|
{ url = "https://files.pythonhosted.org/packages/c4/b6/d7696e4e890d6ae1469935164c9e5215c557671cb78d6e3f458ccceaa632/cryptography-49.0.0-cp311-abi3-manylinux_2_34_ppc64le.whl", hash = "sha256:d0527ce944105f257f605a827d6ebead966c752038b6e8656abb9c5edee6fc68", size = 5265844, upload-time = "2026-06-12T20:01:24.09Z" },
|
||||||
{ url = "https://files.pythonhosted.org/packages/d0/c0/7101d3b7215edcdc90c45da544961fd8ed2d6448f77577460fa75a8443f7/cryptography-48.0.0-cp311-abi3-manylinux_2_34_x86_64.whl", hash = "sha256:bd72e68b06bb1e96913f97dd4901119bc17f39d4586a5adf2d3e47bc2b9d58b5", size = 4743326, upload-time = "2026-05-04T22:57:59.535Z" },
|
{ url = "https://files.pythonhosted.org/packages/a9/3c/f3ad17eecc1a57b0ba236dc01f90e783c51f4a2f35f64777cc4f47a184b2/cryptography-49.0.0-cp311-abi3-manylinux_2_34_x86_64.whl", hash = "sha256:cbc77da8c523d5abd028635ba850a6966fcee2c82e2bf65a41d1d8afe0f98be9", size = 4749290, upload-time = "2026-06-12T20:01:30.848Z" },
|
||||||
{ url = "https://files.pythonhosted.org/packages/ac/d8/5b833bad13016f562ab9d063d68199a4bd121d18458e439515601d3357ec/cryptography-48.0.0-cp311-abi3-musllinux_1_2_aarch64.whl", hash = "sha256:59baa2cb386c4f0b9905bd6eb4c2a79a69a128408fd31d32ca4d7102d4156321", size = 4826672, upload-time = "2026-05-04T22:58:01.996Z" },
|
{ url = "https://files.pythonhosted.org/packages/4f/01/339573cf1023163a400b0b5d16f6d507de413b9f60be6fd1b77feeaf6737/cryptography-49.0.0-cp311-abi3-musllinux_1_2_aarch64.whl", hash = "sha256:b87e65d263b3e5d3bb92a57e2a6638e2f31110fa7aa890c7b2dbba42248d0a3f", size = 4834612, upload-time = "2026-06-12T20:01:29.246Z" },
|
||||||
{ url = "https://files.pythonhosted.org/packages/98/e1/7074eb8bf3c135558c73fc2bcf0f5633f912e6fb87e868a55c454080ef09/cryptography-48.0.0-cp311-abi3-musllinux_1_2_x86_64.whl", hash = "sha256:9249e3cd978541d665967ac2cb2787fd6a62bddf1e75b3e347a594d7dacf4f74", size = 4972574, upload-time = "2026-05-04T22:58:03.968Z" },
|
{ url = "https://files.pythonhosted.org/packages/71/fd/577302e213a1be9468f92d1afef66fcf1ef83d516819d9992ca547f592bd/cryptography-49.0.0-cp311-abi3-musllinux_1_2_x86_64.whl", hash = "sha256:66ec79c3904820572d7e987abdf304281f141d37ad9a489b8e97066e7b9b6459", size = 4980804, upload-time = "2026-06-12T20:01:42.853Z" },
|
||||||
{ url = "https://files.pythonhosted.org/packages/04/70/e5a1b41d325f797f39427aa44ef8baf0be500065ab6d8e10369d850d4a4f/cryptography-48.0.0-cp311-abi3-win32.whl", hash = "sha256:9c459db21422be75e2809370b829a87eb37f74cd785fc4aa9ea1e5f43b47cda4", size = 3294868, upload-time = "2026-05-04T22:58:06.467Z" },
|
{ url = "https://files.pythonhosted.org/packages/1f/09/f42b1d190c5ba75f72062a387f8030d1d75f6ab035788f1d9c4b01de6525/cryptography-49.0.0-cp311-abi3-win_amd64.whl", hash = "sha256:e5dfc1e64de5677cec922ffa8da89c546d0415bf6efdf081842e5d44c84e1f0e", size = 3810026, upload-time = "2026-06-12T20:02:39.262Z" },
|
||||||
{ url = "https://files.pythonhosted.org/packages/f4/ac/8ac51b4a5fc5932eb7ee5c517ba7dc8cd834f0048962b6b352f00f41ebf9/cryptography-48.0.0-cp311-abi3-win_amd64.whl", hash = "sha256:5b012212e08b8dd5edc78ef54da83dd9892fd9105323b3993eff6bea65dc21d7", size = 3817107, upload-time = "2026-05-04T22:58:08.845Z" },
|
{ url = "https://files.pythonhosted.org/packages/ec/9e/db72b3ae7fc9cfad53e630e56c6ae83b9b6ff0bf3718ffb8012d20b3aabf/cryptography-49.0.0-cp314-cp314t-macosx_11_0_arm64.whl", hash = "sha256:73a205dce83953d131a4aa1e0fd917a2fd1c5b1eef251e9d7152efefcbf5caf7", size = 4013892, upload-time = "2026-06-12T20:02:10.735Z" },
|
||||||
{ url = "https://files.pythonhosted.org/packages/6b/84/70e3feea9feea87fd7cbe77efb2712ae1e3e6edf10749dc6e95f4e60e455/cryptography-48.0.0-cp314-cp314t-macosx_10_9_universal2.whl", hash = "sha256:3cb07a3ed6431663cd321ea8a000a1314c74211f823e4177fefa2255e057d1ec", size = 7986556, upload-time = "2026-05-04T22:58:11.172Z" },
|
{ url = "https://files.pythonhosted.org/packages/86/12/c48a424f38db03027be9f7ed5c7dc5de9933dbee992865f98b13727a009d/cryptography-49.0.0-cp314-cp314t-manylinux2014_aarch64.manylinux_2_17_aarch64.whl", hash = "sha256:196ecd6a36e4e9aa10270393bb98d8df88fccee0bf1e5128b91ae4eb4375896d", size = 4678835, upload-time = "2026-06-12T20:02:48.743Z" },
|
||||||
{ url = "https://files.pythonhosted.org/packages/89/6e/18e07a618bb5442ba10cf4df16e99c071365528aa570dfcb8c02e25a303b/cryptography-48.0.0-cp314-cp314t-manylinux2014_aarch64.manylinux_2_17_aarch64.whl", hash = "sha256:8c7378637d7d88016fa6791c159f698b3d3eed28ebf844ac36b9dc04a14dae18", size = 4684776, upload-time = "2026-05-04T22:58:13.712Z" },
|
{ url = "https://files.pythonhosted.org/packages/68/28/8a3ad4653662c93fc44dc4e5d8fd374c25c42e07b34bbfbadf49cf57a5a8/cryptography-49.0.0-cp314-cp314t-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:7abcee80084cda3f7691f3eb1ce480d8df49cec637b429aa35986c1de71738aa", size = 4697239, upload-time = "2026-06-12T20:02:56.03Z" },
|
||||||
{ url = "https://files.pythonhosted.org/packages/be/6a/4ea3b4c6c6759794d5ee2103c304a5076dc4b19ae1f9fe47dba439e159e9/cryptography-48.0.0-cp314-cp314t-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:cc90c0b39b2e3c65ef52c804b72e3c58f8a04ab2a1871272798e5f9572c17d20", size = 4698121, upload-time = "2026-05-04T22:58:16.448Z" },
|
{ url = "https://files.pythonhosted.org/packages/a8/b2/2193fc74f81aee4f9b62733133b73b5176718932ed8f2e4b03fa040480a6/cryptography-49.0.0-cp314-cp314t-manylinux_2_28_aarch64.whl", hash = "sha256:4ae387c9cb68ea569ca17e490d66d8142b81c3cc814bf179974b7d146e490bbb", size = 4685593, upload-time = "2026-06-12T20:02:50.666Z" },
|
||||||
{ url = "https://files.pythonhosted.org/packages/2f/59/6ff6ad6cae03bb887da2a5860b2c9805f8dac969ef01ce563336c49bd1d1/cryptography-48.0.0-cp314-cp314t-manylinux_2_28_aarch64.whl", hash = "sha256:76341972e1eff8b4bea859f09c0d3e64b96ce931b084f9b9b7db8ef364c30eff", size = 4690042, upload-time = "2026-05-04T22:58:18.544Z" },
|
{ url = "https://files.pythonhosted.org/packages/47/f1/1d3eaa243bfc5de4a187b22aa8c048b3e4980bfbe830ac46e6bac2e66947/cryptography-49.0.0-cp314-cp314t-manylinux_2_28_ppc64le.whl", hash = "sha256:f37d847238971164fdbc68ade6f6574aecc9c0af714190e2083429ff68f4ce9d", size = 5289961, upload-time = "2026-06-12T20:01:46.468Z" },
|
||||||
{ url = "https://files.pythonhosted.org/packages/ca/b4/fc334ed8cfd705aca282fe4d8f5ae64a8e0f74932e9feecb344610cf6e4d/cryptography-48.0.0-cp314-cp314t-manylinux_2_28_ppc64le.whl", hash = "sha256:55b7718303bf06a5753dcdccf2f3945cf18ad7bffde41b61226e4db31ab89a9c", size = 5282526, upload-time = "2026-05-04T22:58:20.75Z" },
|
{ url = "https://files.pythonhosted.org/packages/58/39/2d51306721330c486495853eda1c567880ff036de15a14c4b74f399934af/cryptography-49.0.0-cp314-cp314t-manylinux_2_28_x86_64.whl", hash = "sha256:c2bc30226390d60ea19d9f82b19db005fe0452154a23c1c410c12ea801e43561", size = 4731145, upload-time = "2026-06-12T20:02:16.832Z" },
|
||||||
{ url = "https://files.pythonhosted.org/packages/11/08/9f8c5386cc4cd90d8255c7cdd0f5baf459a08502a09de30dc51f553d38dc/cryptography-48.0.0-cp314-cp314t-manylinux_2_28_x86_64.whl", hash = "sha256:a64697c641c7b1b2178e573cbc31c7c6684cd56883a478d75143dbb7118036db", size = 4733116, upload-time = "2026-05-04T22:58:23.627Z" },
|
{ url = "https://files.pythonhosted.org/packages/17/50/983e838c7fd0d87fd8c969bcdd328edaf5f756e38df5281637424c155873/cryptography-49.0.0-cp314-cp314t-manylinux_2_31_armv7l.whl", hash = "sha256:07cab27cc7b7e0fd28e5e26bb9eeedde5c135c868b46de4a27845abe94af6122", size = 4321719, upload-time = "2026-06-12T20:02:52.611Z" },
|
||||||
{ url = "https://files.pythonhosted.org/packages/b8/77/99307d7574045699f8805aa500fa0fb83422d115b5400a064ddd306d7750/cryptography-48.0.0-cp314-cp314t-manylinux_2_31_armv7l.whl", hash = "sha256:561215ea3879cb1cbbf272867e2efda62476f240fb58c64de6b393ae19246741", size = 4316030, upload-time = "2026-05-04T22:58:25.581Z" },
|
{ url = "https://files.pythonhosted.org/packages/a7/f5/8f571d7e27c55bce9f76f026143bcb1e040a4233149ecca0bea5fa5dd5f7/cryptography-49.0.0-cp314-cp314t-manylinux_2_34_aarch64.whl", hash = "sha256:b20133d204d2bb56ba047642199603876c872026ca53e79c35b83772ab2cc505", size = 4685209, upload-time = "2026-06-12T20:02:07.282Z" },
|
||||||
{ url = "https://files.pythonhosted.org/packages/fd/36/a608b98337af3cb2aff4818e406649d30572b7031918b04c87d979495348/cryptography-48.0.0-cp314-cp314t-manylinux_2_34_aarch64.whl", hash = "sha256:ad64688338ed4bc1a6618076ba75fd7194a5f1797ac60b47afe926285adb3166", size = 4689640, upload-time = "2026-05-04T22:58:27.747Z" },
|
{ url = "https://files.pythonhosted.org/packages/e7/84/0e27016a6fc5a0886f797018b26aa42f40c09a82332bff77822a451deaaa/cryptography-49.0.0-cp314-cp314t-manylinux_2_34_ppc64le.whl", hash = "sha256:b970c6da94d5bb18629db453d14f2a1300f6bf59b61e9b82377931ef95504866", size = 5246285, upload-time = "2026-06-12T20:01:32.439Z" },
|
||||||
{ url = "https://files.pythonhosted.org/packages/dd/a6/825010a291b4438aecc1f568bc428189fc1175515223632477c07dc0a6df/cryptography-48.0.0-cp314-cp314t-manylinux_2_34_ppc64le.whl", hash = "sha256:906cbf0670286c6e0044156bc7d4af9cbb0ef6db9f73e52c3ec56ba6bdde5336", size = 5237657, upload-time = "2026-05-04T22:58:29.848Z" },
|
{ url = "https://files.pythonhosted.org/packages/11/2d/5e1fb307cb5931881516b464c98774b3f2c36b5d4bb9a2830253cf553cad/cryptography-49.0.0-cp314-cp314t-manylinux_2_34_x86_64.whl", hash = "sha256:d8ecde755e2e91bf773fc94e8c9d730cd7f2007004cb492263a794ec3899a1c8", size = 4730441, upload-time = "2026-06-12T20:02:01.469Z" },
|
||||||
{ url = "https://files.pythonhosted.org/packages/b9/09/4e76a09b4caa29aad535ddc806f5d4c5d01885bd978bd984fbc6ca032cae/cryptography-48.0.0-cp314-cp314t-manylinux_2_34_x86_64.whl", hash = "sha256:ea8990436d914540a40ab24b6a77c0969695ed52f4a4874c5137ccf7045a7057", size = 4732362, upload-time = "2026-05-04T22:58:32.009Z" },
|
{ url = "https://files.pythonhosted.org/packages/e4/c0/bff5a02ee731d207d6a1ed51732549d8c53d2bc8da1d10ec6f2844201d68/cryptography-49.0.0-cp314-cp314t-musllinux_1_2_aarch64.whl", hash = "sha256:e3fb64c420688e5319ae25113a354015abbd8dffbfbc41781a1ea66fc7622ac3", size = 4815869, upload-time = "2026-06-12T20:01:36.574Z" },
|
||||||
{ url = "https://files.pythonhosted.org/packages/18/78/444fa04a77d0cb95f417dda20d450e13c56ba8e5220fc892a1658f44f882/cryptography-48.0.0-cp314-cp314t-musllinux_1_2_aarch64.whl", hash = "sha256:c18684a7f0cc9a3cb60328f496b8e3372def7c5d2df39ac267878b05565aaaae", size = 4819580, upload-time = "2026-05-04T22:58:34.254Z" },
|
{ url = "https://files.pythonhosted.org/packages/b9/26/814681d14248d95d73d5c3eea0c39a94eb8302df966f670a2c60de90974b/cryptography-49.0.0-cp314-cp314t-musllinux_1_2_x86_64.whl", hash = "sha256:32703d93296f5c1f4b53349ad3a250c2cae0fdecd3a3dd5d47e616d8d616af27", size = 4960948, upload-time = "2026-06-12T20:02:18.688Z" },
|
||||||
{ url = "https://files.pythonhosted.org/packages/38/85/ea67067c70a1fd4be2c63d35eeed82658023021affccc7b17705f8527dd2/cryptography-48.0.0-cp314-cp314t-musllinux_1_2_x86_64.whl", hash = "sha256:9be5aafa5736574f8f15f262adc81b2a9869e2cfe9014d52a44633905b40d52c", size = 4963283, upload-time = "2026-05-04T22:58:36.376Z" },
|
{ url = "https://files.pythonhosted.org/packages/4c/fe/93ecac273d3738939d023612ad12cca9a3740a5345d69fda04134c43fd96/cryptography-49.0.0-cp314-cp314t-win_amd64.whl", hash = "sha256:33cd0565932807baddb67b96dbee92f2c374b5c89dee09fd74079aeb8c8dba61", size = 3799153, upload-time = "2026-06-12T20:01:39.059Z" },
|
||||||
{ url = "https://files.pythonhosted.org/packages/75/54/cc6d0f3deac3e81c7f847e8a189a12b6cdd65059b43dad25d4316abd849a/cryptography-48.0.0-cp314-cp314t-win32.whl", hash = "sha256:c17dfe85494deaeddc5ce251aebd1d60bbe6afc8b62071bb0b469431a000124f", size = 3270954, upload-time = "2026-05-04T22:58:38.791Z" },
|
{ url = "https://files.pythonhosted.org/packages/19/2a/5bb823f5bedcf80718cea7fbc95ec5515cca3769633c4b01a32be7f30e7c/cryptography-49.0.0-cp39-abi3-macosx_11_0_arm64.whl", hash = "sha256:ec5e529fb80935c94fe7b729f9972b50e351a0e6b50aa294fd5cabb109fcc29a", size = 4025947, upload-time = "2026-06-12T20:01:25.745Z" },
|
||||||
{ url = "https://files.pythonhosted.org/packages/49/67/cc947e288c0758a4e5473d1dcb743037ab7785541265a969240b8885441a/cryptography-48.0.0-cp314-cp314t-win_amd64.whl", hash = "sha256:27241b1dc9962e056062a8eef1991d02c3a24569c95975bd2322a8a52c6e5e12", size = 3797313, upload-time = "2026-05-04T22:58:40.746Z" },
|
{ url = "https://files.pythonhosted.org/packages/3d/df/40577043ca124e17012f408ddddaeb213b856336ac82ddb3bc915f39e29f/cryptography-49.0.0-cp39-abi3-manylinux2014_aarch64.manylinux_2_17_aarch64.whl", hash = "sha256:f78ff2c9ed8dc2d036b0f4d640e22522213d047c1b14e61205a7e55c80a494d4", size = 4692429, upload-time = "2026-06-12T20:01:53.628Z" },
|
||||||
{ url = "https://files.pythonhosted.org/packages/f2/63/61d4a4e1c6b6bab6ce1e213cd36a24c415d90e76d78c5eb8577c5541d2e8/cryptography-48.0.0-cp39-abi3-macosx_10_9_universal2.whl", hash = "sha256:58d00498e8933e4a194f3076aee1b4a97dfec1a6da444535755822fe5d8b0b86", size = 7983482, upload-time = "2026-05-04T22:58:43.769Z" },
|
{ url = "https://files.pythonhosted.org/packages/2c/99/2d13299eb3dd27b02dcfaafcc91d6b5cb3329f7cbd6d8f51921acd566c1a/cryptography-49.0.0-cp39-abi3-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:35b151772baff2c74cba7fa290ceaff4c3b11c0c881eb93eb5dbc05a7cfbba18", size = 4700968, upload-time = "2026-06-12T20:02:45.383Z" },
|
||||||
{ url = "https://files.pythonhosted.org/packages/d5/ac/f5b5995b87770c693e2596559ffafe195b4033a57f14a82268a2842953f3/cryptography-48.0.0-cp39-abi3-manylinux2014_aarch64.manylinux_2_17_aarch64.whl", hash = "sha256:614d0949f4790582d2cc25553abd09dd723025f0c0e7c67376a1d77196743d6e", size = 4683266, upload-time = "2026-05-04T22:58:46.064Z" },
|
{ url = "https://files.pythonhosted.org/packages/a5/4d/9c0cd02f95e2602dd5e563da149ee0830abef3537be8b34dc56281ebe27a/cryptography-49.0.0-cp39-abi3-manylinux_2_28_aarch64.whl", hash = "sha256:0f21641cf4b30fca7aee061ced0ec7ad7b073518088b7c9969a297c0ae796c69", size = 4697758, upload-time = "2026-06-12T20:01:41.13Z" },
|
||||||
{ url = "https://files.pythonhosted.org/packages/ec/c6/8b14f67e18338fbc4adb76f66c001f5c3610b3e2d1837f268f47a347dbbb/cryptography-48.0.0-cp39-abi3-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:7ce4bfae76319a532a2dc68f82cc32f5676ee792a983187dac07183690e5c66f", size = 4696228, upload-time = "2026-05-04T22:58:48.22Z" },
|
{ url = "https://files.pythonhosted.org/packages/24/01/186c825898477d77e2324d5360fefe622ff1d8d1963ec0554e2cada8ec77/cryptography-49.0.0-cp39-abi3-manylinux_2_28_ppc64le.whl", hash = "sha256:9e82dcc8e56052715fb18b2429e3bca4823b1629136a2084fc45a9a5cecb9b64", size = 5298863, upload-time = "2026-06-12T20:02:24.579Z" },
|
||||||
{ url = "https://files.pythonhosted.org/packages/ea/73/f808fbae9514bd91b47875b003f13e284c8c6bdfd904b7944e803937eec1/cryptography-48.0.0-cp39-abi3-manylinux_2_28_aarch64.whl", hash = "sha256:2eb992bbd4661238c5a397594c83f5b4dc2bc5b848c365c8f991b6780efcc5c7", size = 4689097, upload-time = "2026-05-04T22:58:50.9Z" },
|
{ url = "https://files.pythonhosted.org/packages/b8/7b/62cbbab75d0659865bf0273790031544a0b16c8072d258f9428dcd8190dc/cryptography-49.0.0-cp39-abi3-manylinux_2_28_x86_64.whl", hash = "sha256:6f2debedf9ca60cf1d5bd466475638af5130f89965605cd818484d19987d3a21", size = 4735983, upload-time = "2026-06-12T20:01:50.14Z" },
|
||||||
{ url = "https://files.pythonhosted.org/packages/93/01/d86632d7d28db8ae83221995752eeb6639ffb374c2d22955648cf8d52797/cryptography-48.0.0-cp39-abi3-manylinux_2_28_ppc64le.whl", hash = "sha256:22a5cb272895dce158b2cacdfdc3debd299019659f42947dbdac6f32d68fe832", size = 5283582, upload-time = "2026-05-04T22:58:53.017Z" },
|
{ url = "https://files.pythonhosted.org/packages/6c/72/3e798c064bc39e471008075d0f9bc9daf77a80879c092e4a8e170c585ed4/cryptography-49.0.0-cp39-abi3-manylinux_2_31_armv7l.whl", hash = "sha256:8c25ceb16df5b9435f3f6a9829204985b0e0cbee3b48aacd432c7d2c850b44d9", size = 4334173, upload-time = "2026-06-12T20:01:44.743Z" },
|
||||||
{ url = "https://files.pythonhosted.org/packages/02/e1/50edc7a50334807cc4791fc4a0ce7468b4a1416d9138eab358bfc9a3d70b/cryptography-48.0.0-cp39-abi3-manylinux_2_28_x86_64.whl", hash = "sha256:2b4d59804e8408e2fea7d1fbaf218e5ec984325221db76e6a241a9abd6cdd95c", size = 4730479, upload-time = "2026-05-04T22:58:55.611Z" },
|
{ url = "https://files.pythonhosted.org/packages/f0/ee/6fca21d1ac73e06f8bef71940abfd4d2f6472b4bca284d770f32bd4086f6/cryptography-49.0.0-cp39-abi3-manylinux_2_34_aarch64.whl", hash = "sha256:28d8b15e6275f12c8a207dc309dfa957903c927d08d0cc937ee3f63f200693cc", size = 4697298, upload-time = "2026-06-12T20:02:20.918Z" },
|
||||||
{ url = "https://files.pythonhosted.org/packages/6f/af/99a582b1b1641ff5911ac559beb45097cf79efd4ead4657f578ef1af2d47/cryptography-48.0.0-cp39-abi3-manylinux_2_31_armv7l.whl", hash = "sha256:984a20b0f62a26f48a3396c72e4bc34c66e356d356bf370053066b3b6d54634a", size = 4326481, upload-time = "2026-05-04T22:58:57.607Z" },
|
{ url = "https://files.pythonhosted.org/packages/67/d0/a5fcd3515f0bae49a7b6d0413cc1bdccdcc1fc0047037a0d480642cdc5d6/cryptography-49.0.0-cp39-abi3-manylinux_2_34_ppc64le.whl", hash = "sha256:6fc361c34fb6aac015ce19435876635e5c6d21db31998b0920f675f131e043b8", size = 5254338, upload-time = "2026-06-12T20:02:22.737Z" },
|
||||||
{ url = "https://files.pythonhosted.org/packages/90/ee/89aa26a06ef0a7d7611788ffd571a7c50e368cc6a4d5eef8b4884e866edb/cryptography-48.0.0-cp39-abi3-manylinux_2_34_aarch64.whl", hash = "sha256:5a5ed8fde7a1d09376ca0b40e68cd59c69fe23b1f9768bd5824f54681626032a", size = 4688713, upload-time = "2026-05-04T22:59:00.077Z" },
|
{ url = "https://files.pythonhosted.org/packages/a0/84/84fe36f19caf857d61cb7fc9c63035a47ffabd84ea12d1d393148efa3615/cryptography-49.0.0-cp39-abi3-manylinux_2_34_x86_64.whl", hash = "sha256:2400ef9c9e2299a25614eb1dea3db54a69b1349efd043bfac9c67630d136df36", size = 4735650, upload-time = "2026-06-12T20:02:41.389Z" },
|
||||||
{ url = "https://files.pythonhosted.org/packages/70/ba/bcb1b0bb7a33d4c7c0c4d4c7874b4a62ae4f56113a5f4baefa362dfb1f0f/cryptography-48.0.0-cp39-abi3-manylinux_2_34_ppc64le.whl", hash = "sha256:8cd666227ef7af430aa5914a9910e0ddd703e75f039cef0825cd0da71b6b711a", size = 5238165, upload-time = "2026-05-04T22:59:02.317Z" },
|
{ url = "https://files.pythonhosted.org/packages/6c/a0/db537264e234f7273a73ec020873d6d6b39dfd8a53db78b550ca8320440e/cryptography-49.0.0-cp39-abi3-musllinux_1_2_aarch64.whl", hash = "sha256:67e1d20ad9ef3a563c59ef22e7a8a0b8210bd26604369ea4a30a7c66aefe504e", size = 4834820, upload-time = "2026-06-12T20:01:51.847Z" },
|
||||||
{ url = "https://files.pythonhosted.org/packages/c9/70/ca4003b1ce5ca3dc3186ada51908c8a9b9ff7d5cab83cc0d43ee14ec144f/cryptography-48.0.0-cp39-abi3-manylinux_2_34_x86_64.whl", hash = "sha256:9071196d81abc88b3516ac8cdfad32e2b66dd4a5393a8e68a961e9161ddc6239", size = 4729947, upload-time = "2026-05-04T22:59:05.255Z" },
|
{ url = "https://files.pythonhosted.org/packages/93/77/8df9eb486495979bccecd1062e2eaf435250e84437040295b57d09048b0b/cryptography-49.0.0-cp39-abi3-musllinux_1_2_x86_64.whl", hash = "sha256:42b0684e0e40cf26122427802486f6d93aea593612603a94fbf260c7eb1e9c1b", size = 4967968, upload-time = "2026-06-12T20:02:12.524Z" },
|
||||||
{ url = "https://files.pythonhosted.org/packages/44/a0/4ec7cf774207905aef1a8d11c3750d5a1db805eb380ee4e16df317870128/cryptography-48.0.0-cp39-abi3-musllinux_1_2_aarch64.whl", hash = "sha256:1e2d54c8be6152856a36f0882ab231e70f8ec7f14e93cf87db8a2ed056bf160c", size = 4822059, upload-time = "2026-05-04T22:59:07.802Z" },
|
{ url = "https://files.pythonhosted.org/packages/c2/e6/f60198ea8d9dfa15fff9ed4ca02ce362f6eadd9ba757dcc50634c4257b63/cryptography-49.0.0-cp39-abi3-win_amd64.whl", hash = "sha256:026ac7423e6fa66872d3bf889be5974507da3944f866f704fa200eadacd00001", size = 3785547, upload-time = "2026-06-12T20:02:26.847Z" },
|
||||||
{ url = "https://files.pythonhosted.org/packages/1e/75/a2e55f99c16fcac7b5d6c1eb19ad8e00799854d6be5ca845f9259eae1681/cryptography-48.0.0-cp39-abi3-musllinux_1_2_x86_64.whl", hash = "sha256:a5da777e32ffed6f85a7b2b3f7c5cbc88c146bfcd0a1d7baf5fcc6c52ee35dd4", size = 4960575, upload-time = "2026-05-04T22:59:09.851Z" },
|
|
||||||
{ url = "https://files.pythonhosted.org/packages/b8/23/6e6f32143ab5d8b36ca848a502c4bcd477ae75b9e1677e3530d669062578/cryptography-48.0.0-cp39-abi3-win32.whl", hash = "sha256:77a2ccbbe917f6710e05ba9adaa25fb5075620bf3ea6fb751997875aff4ae4bd", size = 3279117, upload-time = "2026-05-04T22:59:12.019Z" },
|
|
||||||
{ url = "https://files.pythonhosted.org/packages/9d/9a/0fea98a70cf1749d41d738836f6349d97945f7c89433a259a6c2642eefeb/cryptography-48.0.0-cp39-abi3-win_amd64.whl", hash = "sha256:16cd65b9330583e4619939b3a3843eec1e6e789744bb01e7c7e2e62e33c239c8", size = 3792100, upload-time = "2026-05-04T22:59:14.884Z" },
|
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
@@ -513,11 +560,11 @@ wheels = [
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "distlib"
|
name = "distlib"
|
||||||
version = "0.4.1"
|
version = "0.4.3"
|
||||||
source = { registry = "https://pypi.org/simple" }
|
source = { registry = "https://pypi.org/simple" }
|
||||||
sdist = { url = "https://files.pythonhosted.org/packages/86/b2/d6fc3f2347f43dada79e5ff118493e8109c98400a0e29a1d5264a3aa479b/distlib-0.4.1.tar.gz", hash = "sha256:c3804d0d2d4b5fcd44036eb860cb6660485fcdf5c2aba53dc324d805837ea65b", size = 610526, upload-time = "2026-06-02T11:17:40.691Z" }
|
sdist = { url = "https://files.pythonhosted.org/packages/c9/02/bd72be9134d25ed783ecbbc38a539ffaefbf90c78418c7fb7229600dbac7/distlib-0.4.3.tar.gz", hash = "sha256:f152097224a0ae24be5a0f6bae1b9359af82133bce63f98a95f86cae1aede9ed", size = 615141, upload-time = "2026-06-12T08:04:52.847Z" }
|
||||||
wheels = [
|
wheels = [
|
||||||
{ url = "https://files.pythonhosted.org/packages/25/18/3497c4fa83a76dcb154923fd2075522e8dd6995ecee4093c00ae18160046/distlib-0.4.1-py2.py3-none-any.whl", hash = "sha256:9c2c552c68cbadc619f2d0ed3a69e27c351a3f4c9baa9ffb7df9e9cdc3d19a97", size = 469216, upload-time = "2026-06-02T11:17:38.779Z" },
|
{ url = "https://files.pythonhosted.org/packages/02/08/9c41fb51ab5b43eb21674aff13df270e8ba6c4b29c8624e328dc7a9482af/distlib-0.4.3-py2.py3-none-any.whl", hash = "sha256:4b0ce306c966eb73bc3a7b6abad017c556dadd92c44701562cd528ac7fde4d5b", size = 470628, upload-time = "2026-06-12T08:04:50.506Z" },
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
@@ -596,28 +643,28 @@ wheels = [
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "django-countries"
|
name = "django-countries"
|
||||||
version = "8.2.0"
|
version = "9.0.0"
|
||||||
source = { registry = "https://pypi.org/simple" }
|
source = { registry = "https://pypi.org/simple" }
|
||||||
dependencies = [
|
dependencies = [
|
||||||
{ name = "asgiref" },
|
{ name = "asgiref" },
|
||||||
{ name = "typing-extensions" },
|
{ name = "typing-extensions" },
|
||||||
]
|
]
|
||||||
sdist = { url = "https://files.pythonhosted.org/packages/67/2e/ed67f8f460d1de25ee64fca5d7f219680f944fc8ac5a29fbede3574dc3db/django_countries-8.2.0.tar.gz", hash = "sha256:6df3883180599052c7dfa9a8be0601792441cfb248935dc229ad1ac92e9e39e3", size = 2455542, upload-time = "2025-11-24T19:57:08.071Z" }
|
sdist = { url = "https://files.pythonhosted.org/packages/6e/c1/1e8feb818164c3f23465c08cc3bc1cd7da7101506268a138a1b92ea40339/django_countries-9.0.0.tar.gz", hash = "sha256:a993416af08a8a4e6e866d56b71c7ce92351c81a2543da213cd7899917567a42", size = 614144, upload-time = "2026-06-10T00:39:28.841Z" }
|
||||||
wheels = [
|
wheels = [
|
||||||
{ url = "https://files.pythonhosted.org/packages/20/3c/9ebd7ed021b7c519bac954bc88146bc870e7d3c8db2580fa67268464fd2e/django_countries-8.2.0-py3-none-any.whl", hash = "sha256:2b2617bec7c15dc735bdec38ae89f0058e38fddfffdb19a7f6b75ef1e3d5380f", size = 3776079, upload-time = "2025-11-24T19:57:05.576Z" },
|
{ url = "https://files.pythonhosted.org/packages/5c/bb/5a17b339852f6486d02b4dd0033132082976c71f049ee909ccb42917be52/django_countries-9.0.0-py3-none-any.whl", hash = "sha256:21fce461733c856355c487d1f24b71338599482505004a0c2e521fd574a59fb1", size = 931759, upload-time = "2026-06-10T00:39:26.851Z" },
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "django-debug-toolbar"
|
name = "django-debug-toolbar"
|
||||||
version = "6.3.0"
|
version = "7.0.0"
|
||||||
source = { registry = "https://pypi.org/simple" }
|
source = { registry = "https://pypi.org/simple" }
|
||||||
dependencies = [
|
dependencies = [
|
||||||
{ name = "django" },
|
{ name = "django" },
|
||||||
{ name = "sqlparse" },
|
{ name = "sqlparse" },
|
||||||
]
|
]
|
||||||
sdist = { url = "https://files.pythonhosted.org/packages/d8/ea/b62673424dd72d2dbf5adf4145281a421d5792f47380d9bc8e3b11e1a769/django_debug_toolbar-6.3.0.tar.gz", hash = "sha256:f830a86fe02e17f625a22cfbed24a5bd1500762e201ec959c50efb0f9327282b", size = 334079, upload-time = "2026-04-02T16:07:01.385Z" }
|
sdist = { url = "https://files.pythonhosted.org/packages/1e/ac/3ac674f99c64bfbcd9ae3d7f5f3577f23ea52884e5ac36842e1f024dce03/django_debug_toolbar-7.0.0.tar.gz", hash = "sha256:ef7494c5b459c149e87cc2da88d86e944064945e86bd7b2d879093586b5fefbf", size = 359560, upload-time = "2026-06-19T00:21:23.346Z" }
|
||||||
wheels = [
|
wheels = [
|
||||||
{ url = "https://files.pythonhosted.org/packages/7d/9e/d8c3c845f4b5ccac7377c19f4049e7e00c6f121846a81f69a497b45734df/django_debug_toolbar-6.3.0-py3-none-any.whl", hash = "sha256:a199ce3d0f884739a9096835ad417479fede05f3b3c4824bc8b354721ba8f629", size = 298304, upload-time = "2026-04-02T16:06:59.617Z" },
|
{ url = "https://files.pythonhosted.org/packages/4b/ab/684a56624f9ed35127e203e52d2c241f3b7b70d37cfa8cb2ba4fc8e1e8d7/django_debug_toolbar-7.0.0-py3-none-any.whl", hash = "sha256:656161388ce48384276342eeb16d532113ec670816fa1546cc3753730aa51b3d", size = 302038, upload-time = "2026-06-19T00:21:21.531Z" },
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
@@ -670,7 +717,7 @@ wheels = [
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "django-ninja-extra"
|
name = "django-ninja-extra"
|
||||||
version = "0.31.4"
|
version = "0.31.5"
|
||||||
source = { registry = "https://pypi.org/simple" }
|
source = { registry = "https://pypi.org/simple" }
|
||||||
dependencies = [
|
dependencies = [
|
||||||
{ name = "asgiref" },
|
{ name = "asgiref" },
|
||||||
@@ -679,9 +726,9 @@ dependencies = [
|
|||||||
{ name = "django-ninja" },
|
{ name = "django-ninja" },
|
||||||
{ name = "injector" },
|
{ name = "injector" },
|
||||||
]
|
]
|
||||||
sdist = { url = "https://files.pythonhosted.org/packages/7c/31/8f9f76ef9e1e40fb0e316d89b8d356f9a74d4b4eb149f6b46def4d1ab16e/django_ninja_extra-0.31.4.tar.gz", hash = "sha256:c5efc13bead5e49ac90b83f8739689345c260e412f530d78825740a67a8ca99f", size = 62357, upload-time = "2026-03-31T13:47:06.901Z" }
|
sdist = { url = "https://files.pythonhosted.org/packages/ef/7f/d462683fae69ccd6526678d3013da1ffb3cd58e8f1a9ad6396aeb1cc07d1/django_ninja_extra-0.31.5.tar.gz", hash = "sha256:c687557580f7d59698786ac78e1860e7bafccf6a662e453ff579ae13a9b15e48", size = 62847, upload-time = "2026-06-14T15:05:27.983Z" }
|
||||||
wheels = [
|
wheels = [
|
||||||
{ url = "https://files.pythonhosted.org/packages/74/bc/bd30b4f6625da927b09f810e64f2a29aea83731ba9641cbed1f828986cd5/django_ninja_extra-0.31.4-py3-none-any.whl", hash = "sha256:fb40879364808344e16b690990bbd669dccd0a0f4a2844294bf07ec3eb1b5375", size = 83562, upload-time = "2026-03-31T13:47:05.887Z" },
|
{ url = "https://files.pythonhosted.org/packages/a2/19/5a50a048dfeb653d2ec3f425edf258a6137c00f156560ae4ad87834188fc/django_ninja_extra-0.31.5-py3-none-any.whl", hash = "sha256:a2a38266ef35582e1eea802009893c0889fea688cf30f89e32a389431ebdd7b0", size = 84152, upload-time = "2026-06-14T15:05:26.808Z" },
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
@@ -730,14 +777,14 @@ wheels = [
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "django-timezone-field"
|
name = "django-timezone-field"
|
||||||
version = "7.2.1"
|
version = "7.2.2"
|
||||||
source = { registry = "https://pypi.org/simple" }
|
source = { registry = "https://pypi.org/simple" }
|
||||||
dependencies = [
|
dependencies = [
|
||||||
{ name = "django" },
|
{ name = "django" },
|
||||||
]
|
]
|
||||||
sdist = { url = "https://files.pythonhosted.org/packages/da/05/9b93a66452cdb8a08ab26f08d5766d2332673e659a8b2aeb73f2a904d421/django_timezone_field-7.2.1.tar.gz", hash = "sha256:def846f9e7200b7b8f2a28fcce2b78fb2d470f6a9f272b07c4e014f6ba4c6d2e", size = 13096, upload-time = "2025-12-06T23:50:44.591Z" }
|
sdist = { url = "https://files.pythonhosted.org/packages/12/0b/22654abc2355f3b84e3e5b9d26569639c15d04b96d7186f3a477ec45c1ef/django_timezone_field-7.2.2.tar.gz", hash = "sha256:a004d0b19fe10bf5964cb21a65b36324b16a61879e4711c0dafdf8d6253e8ebc", size = 13158, upload-time = "2026-06-06T05:28:23.638Z" }
|
||||||
wheels = [
|
wheels = [
|
||||||
{ url = "https://files.pythonhosted.org/packages/41/7f/d885667401515b467f84569c56075bc9add72c9fd425fca51a25f4c997e1/django_timezone_field-7.2.1-py3-none-any.whl", hash = "sha256:276915b72c5816f57c3baf9e43f816c695ef940d1b21f91ebf6203c09bf4ad44", size = 13284, upload-time = "2025-12-06T23:50:43.302Z" },
|
{ url = "https://files.pythonhosted.org/packages/2b/5f/c8dfb67105c4ef391a3e9d0bcd35b7eae4c4c9d023d612c3999ae1cb32ef/django_timezone_field-7.2.2-py3-none-any.whl", hash = "sha256:30354d0f37462a0b9b5c289e271580a6be9b58dea30e7bf88435372882c8fa7a", size = 13322, upload-time = "2026-06-06T05:28:22.454Z" },
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
@@ -789,23 +836,23 @@ wheels = [
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "faker"
|
name = "faker"
|
||||||
version = "40.21.0"
|
version = "40.23.0"
|
||||||
source = { registry = "https://pypi.org/simple" }
|
source = { registry = "https://pypi.org/simple" }
|
||||||
dependencies = [
|
dependencies = [
|
||||||
{ name = "tzdata", marker = "sys_platform == 'win32'" },
|
{ name = "tzdata", marker = "sys_platform == 'win32'" },
|
||||||
]
|
]
|
||||||
sdist = { url = "https://files.pythonhosted.org/packages/e8/6f/d7b251fb31de7dce0e482680bf7ca876aa0043f475c04aeefa1459ea80d4/faker-40.21.0.tar.gz", hash = "sha256:2fdee1b650a723a54432db9c6dfe17cfa29d1adc8bd60520444a07698524ba4d", size = 1970295, upload-time = "2026-06-02T17:53:46.27Z" }
|
sdist = { url = "https://files.pythonhosted.org/packages/f3/d6/fc071e5754815d9058e12ab549cc88e90f8f4ecf4dc33b6b750cdf4b622d/faker-40.23.0.tar.gz", hash = "sha256:f135e563f1f95f19346bb680bc2e43570bc43b7893e566023746f51f32c69dfc", size = 1972975, upload-time = "2026-06-10T20:53:21.611Z" }
|
||||||
wheels = [
|
wheels = [
|
||||||
{ url = "https://files.pythonhosted.org/packages/bb/77/6adb5a9dcd028f687f81fc9f789591f9572cb5a46454337122add004e134/faker-40.21.0-py3-none-any.whl", hash = "sha256:cb6601b2ae8e128895dc96814d271eab6b930a2d2d7932c6f9ff26785c24ee18", size = 2008808, upload-time = "2026-06-02T17:53:44.346Z" },
|
{ url = "https://files.pythonhosted.org/packages/64/5f/824e6fb3e9d63408151dc9173994fa65bde620a67dde3a59354f5aecd497/faker-40.23.0-py3-none-any.whl", hash = "sha256:775922453e54afa42eaf60eac478fa3a969357f224d09a8022b93e3ad88f18ae", size = 2013046, upload-time = "2026-06-10T20:53:19.226Z" },
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "filelock"
|
name = "filelock"
|
||||||
version = "3.29.1"
|
version = "3.29.4"
|
||||||
source = { registry = "https://pypi.org/simple" }
|
source = { registry = "https://pypi.org/simple" }
|
||||||
sdist = { url = "https://files.pythonhosted.org/packages/1f/f9/f38573ed5844586db374d085911740a501ccfa373b455fc9413f09f85237/filelock-3.29.1.tar.gz", hash = "sha256:d97e6b1b9757569626c58caa07dc4beb1613f4a2938b1e8cc81afca398906c9e", size = 59335, upload-time = "2026-06-03T15:19:04.053Z" }
|
sdist = { url = "https://files.pythonhosted.org/packages/e6/dc/be6cbe99670cd6e4ad387123647cb08e0c32975e223f82551e914c5568a6/filelock-3.29.4.tar.gz", hash = "sha256:10cdb3656fc44541cdf30652a93fb10ec6b05325620eb316bd26893e4201538a", size = 63028, upload-time = "2026-06-13T16:12:00.744Z" }
|
||||||
wheels = [
|
wheels = [
|
||||||
{ url = "https://files.pythonhosted.org/packages/4c/a0/614c5fe402fd88951df45f4dda2fa3b4e17a99ecd92340771929169b3b95/filelock-3.29.1-py3-none-any.whl", hash = "sha256:85199dfd706869641b72b2e8955d5416a4b2b7dc4b0e8e6d97b4cc1299a6983b", size = 40750, upload-time = "2026-06-03T15:19:02.959Z" },
|
{ url = "https://files.pythonhosted.org/packages/13/37/a065dc3bd6e49423a6532c642ca7378d3f467b1ef44c2800c937af7f9739/filelock-3.29.4-py3-none-any.whl", hash = "sha256:dac1648087d5115554850d113e7dd8c83ab2d38e3435dde2d4f163847e57b767", size = 42757, upload-time = "2026-06-13T16:11:59.582Z" },
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
@@ -834,11 +881,11 @@ wheels = [
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "griffelib"
|
name = "griffelib"
|
||||||
version = "2.0.2"
|
version = "2.1.0"
|
||||||
source = { registry = "https://pypi.org/simple" }
|
source = { registry = "https://pypi.org/simple" }
|
||||||
sdist = { url = "https://files.pythonhosted.org/packages/9d/82/74f4a3310cdabfbb10da554c3a672847f1ed33c6f61dd472681ce7f1fe67/griffelib-2.0.2.tar.gz", hash = "sha256:3cf20b3bc470e83763ffbf236e0076b1211bac1bc67de13daf494640f2de707e", size = 166461, upload-time = "2026-03-27T11:34:51.091Z" }
|
sdist = { url = "https://files.pythonhosted.org/packages/33/e4/8d187ea29c2e30b3a09505c567513077d6117861bde1fbd997a167f262ec/griffelib-2.1.0.tar.gz", hash = "sha256:762a186d2c6fd6794d4ea20d428d597ffb857cb56b66421651cbba15bdd5e813", size = 216234, upload-time = "2026-06-19T12:05:42.278Z" }
|
||||||
wheels = [
|
wheels = [
|
||||||
{ url = "https://files.pythonhosted.org/packages/11/8c/c9138d881c79aa0ea9ed83cbd58d5ca75624378b38cee225dcf5c42cc91f/griffelib-2.0.2-py3-none-any.whl", hash = "sha256:925c857658fb1ba40c0772c37acbc2ab650bd794d9c1b9726922e36ea4117ea1", size = 142357, upload-time = "2026-03-27T11:34:46.275Z" },
|
{ url = "https://files.pythonhosted.org/packages/e4/d3/5268aeabf2ad82658c4e2ff3a060648d0f02f3926cb53247c0e4d0dab49e/griffelib-2.1.0-py3-none-any.whl", hash = "sha256:cc7b3d2d2865ad0b909fcc38086e3f554b5ea7acbaa7bbb7ecaa3f5dfb7d9f00", size = 142560, upload-time = "2026-06-19T12:05:38.742Z" },
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
@@ -1269,15 +1316,6 @@ wheels = [
|
|||||||
{ url = "https://files.pythonhosted.org/packages/2c/19/04f9b178c2d8a15b076c8b5140708fa6ffc5601fb6f1e975537072df5b2a/mergedeep-1.3.4-py3-none-any.whl", hash = "sha256:70775750742b25c0d8f36c55aed03d24c3384d17c951b3175d898bd778ef0307", size = 6354, upload-time = "2021-02-05T18:55:29.583Z" },
|
{ url = "https://files.pythonhosted.org/packages/2c/19/04f9b178c2d8a15b076c8b5140708fa6ffc5601fb6f1e975537072df5b2a/mergedeep-1.3.4-py3-none-any.whl", hash = "sha256:70775750742b25c0d8f36c55aed03d24c3384d17c951b3175d898bd778ef0307", size = 6354, upload-time = "2021-02-05T18:55:29.583Z" },
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "mistune"
|
|
||||||
version = "3.2.1"
|
|
||||||
source = { registry = "https://pypi.org/simple" }
|
|
||||||
sdist = { url = "https://files.pythonhosted.org/packages/ca/84/620cc3f7e3adf6f5067e10f4dbae71295d8f9e16d5d3f9ef97c40f2f592c/mistune-3.2.1.tar.gz", hash = "sha256:7c8e5501d38bac1582e067e46c8343f17d57ea1aaa735823f3aba1fd59c88a28", size = 98003, upload-time = "2026-05-03T14:33:22.312Z" }
|
|
||||||
wheels = [
|
|
||||||
{ url = "https://files.pythonhosted.org/packages/2a/7f/a946aa4f8752b37102b41e64dca18a1976ac705c3a0d1dfe74d820a02552/mistune-3.2.1-py3-none-any.whl", hash = "sha256:78cdb0ba5e938053ccf63651b352508d2efa9411dc8810bfb05f2dc5140c0048", size = 53749, upload-time = "2026-05-03T14:33:20.551Z" },
|
|
||||||
]
|
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "mkdocs"
|
name = "mkdocs"
|
||||||
version = "1.6.1"
|
version = "1.6.1"
|
||||||
@@ -1393,28 +1431,28 @@ wheels = [
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "mkdocstrings-python"
|
name = "mkdocstrings-python"
|
||||||
version = "2.0.4"
|
version = "2.0.5"
|
||||||
source = { registry = "https://pypi.org/simple" }
|
source = { registry = "https://pypi.org/simple" }
|
||||||
dependencies = [
|
dependencies = [
|
||||||
{ name = "griffelib" },
|
{ name = "griffelib" },
|
||||||
{ name = "mkdocs-autorefs" },
|
{ name = "mkdocs-autorefs" },
|
||||||
{ name = "mkdocstrings" },
|
{ name = "mkdocstrings" },
|
||||||
]
|
]
|
||||||
sdist = { url = "https://files.pythonhosted.org/packages/a4/b4/5fed370d8ebd96e4e399460a7146ae989263f16588b05a6facd6dbd51e60/mkdocstrings_python-2.0.4.tar.gz", hash = "sha256:58c73c5d358e64e9b1673447663f4a2f8a8941e392e225fc0a0c893758cc452f", size = 199219, upload-time = "2026-06-05T08:13:01.819Z" }
|
sdist = { url = "https://files.pythonhosted.org/packages/b1/b6/e858701499d57eee8b3fd8e78168083956c6683ddbe727b46758b19e1119/mkdocstrings_python-2.0.5.tar.gz", hash = "sha256:3a4d92556ad39637e88af94a5374213af9a8e3040c3824ceaed04b486c017594", size = 199578, upload-time = "2026-06-19T10:41:08.868Z" }
|
||||||
wheels = [
|
wheels = [
|
||||||
{ url = "https://files.pythonhosted.org/packages/5e/e3/00ec594aef5f55522e6d373bc2ac53e53a8f5e9ae32f2d6854b0de4270f3/mkdocstrings_python-2.0.4-py3-none-any.whl", hash = "sha256:fd87c173e1e719a85997b6d4f852cdc55f36710e0ed08da3a7bd9abe79c9db00", size = 104790, upload-time = "2026-06-05T08:13:00.393Z" },
|
{ url = "https://files.pythonhosted.org/packages/d1/fc/10ab7e80650a9c9e8f4f1105f8c8e73567f88ed0c06ada589ab81d38687c/mkdocstrings_python-2.0.5-py3-none-any.whl", hash = "sha256:30c837bbff016549f659fcba6539ac351303f0fd7e713c89a040611072236e9d", size = 104951, upload-time = "2026-06-19T10:41:07.378Z" },
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "model-bakery"
|
name = "model-bakery"
|
||||||
version = "1.23.4"
|
version = "1.24.0"
|
||||||
source = { registry = "https://pypi.org/simple" }
|
source = { registry = "https://pypi.org/simple" }
|
||||||
dependencies = [
|
dependencies = [
|
||||||
{ name = "django" },
|
{ name = "django" },
|
||||||
]
|
]
|
||||||
sdist = { url = "https://files.pythonhosted.org/packages/41/51/d3cfd4ab5c1cb9f889c604dc96cc0f1d7a52972ee28fe7a44a9dd705521a/model_bakery-1.23.4.tar.gz", hash = "sha256:0cd8e958e229734bd41feffdcb513a0f079c79c9ddb2e0aad11ed2c23f6d43d5", size = 23812, upload-time = "2026-03-27T09:28:39.75Z" }
|
sdist = { url = "https://files.pythonhosted.org/packages/f9/49/3e5b51d7af52bf39e348767c1feb16c97d18654a8e3f3306eb4b899e98cf/model_bakery-1.24.0.tar.gz", hash = "sha256:6469223c9fb0eccb021d5c33667b914e9208dd2282d7dc1e55394c2310a7687d", size = 28372, upload-time = "2026-06-23T21:55:23.19Z" }
|
||||||
wheels = [
|
wheels = [
|
||||||
{ url = "https://files.pythonhosted.org/packages/95/88/55c8e0a873e7a0f8e0d6c5ca236512cc37555632be178e7ba72bfbe0a619/model_bakery-1.23.4-py3-none-any.whl", hash = "sha256:65bfa0405d3ea60aca8c21e7e184c6617d6c8d32d0493cc75232a4476f471514", size = 25984, upload-time = "2026-03-27T09:28:38.439Z" },
|
{ url = "https://files.pythonhosted.org/packages/60/8e/9108507501846c9ee2a1b277d35d1f92ae251852bbd1527f6dbf2665d94a/model_bakery-1.24.0-py3-none-any.whl", hash = "sha256:d1f739cfc43e8d403d04734a18c73c8e677f655dd08719e35342c2f5ada1d7e9", size = 30819, upload-time = "2026-06-23T21:55:21.911Z" },
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
@@ -1476,11 +1514,11 @@ wheels = [
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "phonenumbers"
|
name = "phonenumbers"
|
||||||
version = "9.0.32"
|
version = "9.0.33"
|
||||||
source = { registry = "https://pypi.org/simple" }
|
source = { registry = "https://pypi.org/simple" }
|
||||||
sdist = { url = "https://files.pythonhosted.org/packages/ef/11/ba7611cadc8c99b797416d0dada535c02890dc21b759dfef60a3751d2e20/phonenumbers-9.0.32.tar.gz", hash = "sha256:108ad0237202d2f6cf4b342fac411f22808d85187c3a366152a2af7ed3202a8e", size = 2306598, upload-time = "2026-06-05T05:48:38.909Z" }
|
sdist = { url = "https://files.pythonhosted.org/packages/75/37/dfc4cf24169f1a7169ebaedaf896c818f0add8603409d1e748e3085ccdc0/phonenumbers-9.0.33.tar.gz", hash = "sha256:9ab8a02b940b90c64f3866c0b25a30e567ddf7bb9836a3e11efdb0478f65fc1c", size = 2306756, upload-time = "2026-06-22T10:23:33.428Z" }
|
||||||
wheels = [
|
wheels = [
|
||||||
{ url = "https://files.pythonhosted.org/packages/c6/e9/1ca526105e792b7ed752fd0ff5732ab01185f2deb719ae6f30183fb21143/phonenumbers-9.0.32-py2.py3-none-any.whl", hash = "sha256:fbcd40d3b11920ee77b1d34a54c3b64c6648a90b8e37222eb62e7fafb87db3e7", size = 2595438, upload-time = "2026-06-05T05:48:36.066Z" },
|
{ url = "https://files.pythonhosted.org/packages/e6/29/f7e30e3dbd3c7e3d9c4a55006112c04ee62b4765a31f21bcc28c253ac3f1/phonenumbers-9.0.33-py2.py3-none-any.whl", hash = "sha256:ba1d0da52711d5fdda6b2b673b2621fe80774fc5d1b2e5a6ef783396b0343186", size = 2595422, upload-time = "2026-06-22T10:23:29.925Z" },
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
@@ -1791,20 +1829,20 @@ wheels = [
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "pymdown-extensions"
|
name = "pymdown-extensions"
|
||||||
version = "10.21.3"
|
version = "11.0"
|
||||||
source = { registry = "https://pypi.org/simple" }
|
source = { registry = "https://pypi.org/simple" }
|
||||||
dependencies = [
|
dependencies = [
|
||||||
{ name = "markdown" },
|
{ name = "markdown" },
|
||||||
{ name = "pyyaml" },
|
{ name = "pyyaml" },
|
||||||
]
|
]
|
||||||
sdist = { url = "https://files.pythonhosted.org/packages/9e/26/d1015444da4d952a1ca487a236b522eb979766f0295a0bd0c5fc089989a9/pymdown_extensions-10.21.3.tar.gz", hash = "sha256:72cfcf55f07aea0d4af2c4f11dd4e52466ddfb1bb819673146398e0bd3a77354", size = 854140, upload-time = "2026-05-13T12:57:32.267Z" }
|
sdist = { url = "https://files.pythonhosted.org/packages/47/67/f1e79672a5f91985577c7984c9709ca110e4fd37fe7fd167b60422e6ccc2/pymdown_extensions-11.0.tar.gz", hash = "sha256:8269cef0247f9e2d0a62fcea10860aba05c1cbab5470fd4b63230b96434dc589", size = 857049, upload-time = "2026-06-23T02:27:45.146Z" }
|
||||||
wheels = [
|
wheels = [
|
||||||
{ url = "https://files.pythonhosted.org/packages/7e/85/545a951eecc270fcd688288c600017e2050a1aacb56c711d208586d3e470/pymdown_extensions-10.21.3-py3-none-any.whl", hash = "sha256:d7a5d08014fc571e80ca21dd6f854e31f94c489800350564d55d15b3c41e76b6", size = 269002, upload-time = "2026-05-13T12:57:30.296Z" },
|
{ url = "https://files.pythonhosted.org/packages/af/b6/1ae53367e28b9cffa3be7574e13fbe4589694272fd47710fbdbafd3d63c6/pymdown_extensions-11.0-py3-none-any.whl", hash = "sha256:fbc4acb641814fa9d17521bbd21a5240ef739a662f11c06330c4b78c93e954d6", size = 269415, upload-time = "2026-06-23T02:27:43.826Z" },
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "pytest"
|
name = "pytest"
|
||||||
version = "9.0.3"
|
version = "9.1.1"
|
||||||
source = { registry = "https://pypi.org/simple" }
|
source = { registry = "https://pypi.org/simple" }
|
||||||
dependencies = [
|
dependencies = [
|
||||||
{ name = "colorama", marker = "sys_platform == 'win32'" },
|
{ name = "colorama", marker = "sys_platform == 'win32'" },
|
||||||
@@ -1813,9 +1851,9 @@ dependencies = [
|
|||||||
{ name = "pluggy" },
|
{ name = "pluggy" },
|
||||||
{ name = "pygments" },
|
{ name = "pygments" },
|
||||||
]
|
]
|
||||||
sdist = { url = "https://files.pythonhosted.org/packages/7d/0d/549bd94f1a0a402dc8cf64563a117c0f3765662e2e668477624baeec44d5/pytest-9.0.3.tar.gz", hash = "sha256:b86ada508af81d19edeb213c681b1d48246c1a91d304c6c81a427674c17eb91c", size = 1572165, upload-time = "2026-04-07T17:16:18.027Z" }
|
sdist = { url = "https://files.pythonhosted.org/packages/e4/47/b9efed96c114afcfa3c9d3fe98a76a1d14c74a9e266d397cf6eb64be5e01/pytest-9.1.1.tar.gz", hash = "sha256:1088fbde8f2b49d95a549a195707afa7a76a3ce9bcadc26b6d71f0ffda5fe313", size = 1636369, upload-time = "2026-06-19T10:58:32.857Z" }
|
||||||
wheels = [
|
wheels = [
|
||||||
{ url = "https://files.pythonhosted.org/packages/d4/24/a372aaf5c9b7208e7112038812994107bc65a84cd00e0354a88c2c77a617/pytest-9.0.3-py3-none-any.whl", hash = "sha256:2c5efc453d45394fdd706ade797c0a81091eccd1d6e4bccfcd476e2b8e0ab5d9", size = 375249, upload-time = "2026-04-07T17:16:16.13Z" },
|
{ url = "https://files.pythonhosted.org/packages/24/25/1de2678b631f5a49215c6c96fff41ba892b0a34df68d6d80292b1b48aa7f/pytest-9.1.1-py3-none-any.whl", hash = "sha256:37a86b45efb9a47a61a36449063e8e18d0cab3161329fc099eb21783169c4f0c", size = 386536, upload-time = "2026-06-19T10:58:31.347Z" },
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
@@ -1867,15 +1905,15 @@ wheels = [
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "python-discovery"
|
name = "python-discovery"
|
||||||
version = "1.4.0"
|
version = "1.4.2"
|
||||||
source = { registry = "https://pypi.org/simple" }
|
source = { registry = "https://pypi.org/simple" }
|
||||||
dependencies = [
|
dependencies = [
|
||||||
{ name = "filelock" },
|
{ name = "filelock" },
|
||||||
{ name = "platformdirs" },
|
{ name = "platformdirs" },
|
||||||
]
|
]
|
||||||
sdist = { url = "https://files.pythonhosted.org/packages/a6/12/38c1a0b1e64806780c9563e3fc9f6e472251839662587cfbe9bfaf2ae10a/python_discovery-1.4.0.tar.gz", hash = "sha256:eb8bc7daad3c226c147e45bb4e970a1feb1bf4048ee178e6db59e197b8010ce3", size = 68455, upload-time = "2026-05-28T01:15:37.639Z" }
|
sdist = { url = "https://files.pythonhosted.org/packages/0b/1a/cbbaf13b730abb0a16b964d984e19f2fe520c21a4dc664051359a3f5a9e7/python_discovery-1.4.2.tar.gz", hash = "sha256:8f3746c4b4968d22afbb97d36e1a0e5b66e6c0f297290f2e95f05b9b8bf18690", size = 70277, upload-time = "2026-06-11T16:10:42.383Z" }
|
||||||
wheels = [
|
wheels = [
|
||||||
{ url = "https://files.pythonhosted.org/packages/c8/8d/3d316429f65029532bb1e28ff77b797d86b5ac3915bb44ca4e19aa283d43/python_discovery-1.4.0-py3-none-any.whl", hash = "sha256:26ed78d703e234879a66244c7d4114563fb13ec5cd30a2d1357e5fb4850782da", size = 33217, upload-time = "2026-05-28T01:15:36.573Z" },
|
{ url = "https://files.pythonhosted.org/packages/1a/82/a70006589557f267f15bd384c0642ad49f0d97b690c3a05b166b9dcbad3b/python_discovery-1.4.2-py3-none-any.whl", hash = "sha256:475803f53b7b2ed6e490e27373f9d8340f7d2eebf9acdaf645d7d714c97bb500", size = 33886, upload-time = "2026-06-11T16:10:41.192Z" },
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
@@ -1961,15 +1999,15 @@ hiredis = [
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "reportlab"
|
name = "reportlab"
|
||||||
version = "4.5.1"
|
version = "5.0.0"
|
||||||
source = { registry = "https://pypi.org/simple" }
|
source = { registry = "https://pypi.org/simple" }
|
||||||
dependencies = [
|
dependencies = [
|
||||||
{ name = "charset-normalizer" },
|
{ name = "charset-normalizer" },
|
||||||
{ name = "pillow" },
|
{ name = "pillow" },
|
||||||
]
|
]
|
||||||
sdist = { url = "https://files.pythonhosted.org/packages/4d/3f/b3861b7e40c9d66f4a04e018958d681d16b948bfd1963c962d43a8c23f66/reportlab-4.5.1.tar.gz", hash = "sha256:9fdf68f4de9171ec66acb4a5feed8f8ca2af43479e707a6fbb0daa75d88e5494", size = 3939748, upload-time = "2026-05-12T10:14:13.663Z" }
|
sdist = { url = "https://files.pythonhosted.org/packages/41/d6/4b7b0cf56880eb96533e607967be6a939e344675601e033d113a0bfa1f4e/reportlab-5.0.0.tar.gz", hash = "sha256:e4494a0c6623ae213bb856fba523171b2b54a7bf629fda02d5e525a7b899a784", size = 3701928, upload-time = "2026-06-18T11:34:31.145Z" }
|
||||||
wheels = [
|
wheels = [
|
||||||
{ url = "https://files.pythonhosted.org/packages/a7/45/ea7fad10122440de6e845568d106bffdc456ca0e8a1d8ae10b46016087e4/reportlab-4.5.1-py3-none-any.whl", hash = "sha256:06fce8cb56c83307cfa4909cdf4e6a2ddbb44e5d6ef4d2edca896d7e9769f091", size = 1957812, upload-time = "2026-05-12T10:14:10.622Z" },
|
{ url = "https://files.pythonhosted.org/packages/a3/07/70085c17a369605f15e301d10ab902115019b1126c7253d964afc230c7d6/reportlab-5.0.0-py3-none-any.whl", hash = "sha256:9d5a3affa84919e1111ede580031266a570e93b1ce388219621347965ff1d93c", size = 1956710, upload-time = "2026-06-18T11:34:29.07Z" },
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
@@ -2036,40 +2074,40 @@ wheels = [
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "ruff"
|
name = "ruff"
|
||||||
version = "0.15.16"
|
version = "0.15.19"
|
||||||
source = { registry = "https://pypi.org/simple" }
|
source = { registry = "https://pypi.org/simple" }
|
||||||
sdist = { url = "https://files.pythonhosted.org/packages/a6/bd/5f7ec371001337d8fa61701c186ff8b613ecac1651848c5950f4c4d5f2e9/ruff-0.15.16.tar.gz", hash = "sha256:d05e78d38c78caf020b03789e25106c93017db5a0cb6e2819885018c61343b78", size = 4714267, upload-time = "2026-06-04T16:33:09.974Z" }
|
sdist = { url = "https://files.pythonhosted.org/packages/d5/e6/15800dfde183a1a106594016c912b4c12d050a301989d1aca6cb63759fe8/ruff-0.15.19.tar.gz", hash = "sha256:edc27f7172a93b32b102687009d6a588508815072141543ae603a8b9b0823063", size = 4772071, upload-time = "2026-06-24T01:10:46.942Z" }
|
||||||
wheels = [
|
wheels = [
|
||||||
{ url = "https://files.pythonhosted.org/packages/0c/42/53ef1c3953f157956db9bf7861e3bc50b9b887ce93300aa48cdba8336fe6/ruff-0.15.16-py3-none-linux_armv6l.whl", hash = "sha256:6ac3c0b3969cc6cf6b158c4e2f8f682acb58e7d700d8a44b65ecdc72d66ab0b2", size = 10709025, upload-time = "2026-06-04T16:32:51.935Z" },
|
{ url = "https://files.pythonhosted.org/packages/88/4c/9ded7626c39a0440c575bf69e2bf500d443388272c842662c59852ee7fcd/ruff-0.15.19-py3-none-linux_armv6l.whl", hash = "sha256:922d1eb283161564759bd49f507e91dc6112c15da8bd5b84ed714e086243cf86", size = 10950859, upload-time = "2026-06-24T01:10:38.491Z" },
|
||||||
{ url = "https://files.pythonhosted.org/packages/93/9a/a79159346f19134a956607754e57d8d128f7a4c00f4ad2f7514d224c172c/ruff-0.15.16-py3-none-macosx_10_12_x86_64.whl", hash = "sha256:197c207ed75ffba54a0dec23db4aa939a27a3053073e085e0042433cbdc58e4a", size = 11063550, upload-time = "2026-06-04T16:32:42.24Z" },
|
{ url = "https://files.pythonhosted.org/packages/fb/ef/c211505ece1d00ef493d58e54e3b6383c946a21e9874774eb531f2512cf3/ruff-0.15.19-py3-none-macosx_10_12_x86_64.whl", hash = "sha256:4d190d8f62a0b94aba8f721116538a9ee29b1e74d26650846ba9b99f0ae21c40", size = 11294529, upload-time = "2026-06-24T01:10:36.481Z" },
|
||||||
{ url = "https://files.pythonhosted.org/packages/bc/72/3ce2ac000a5299ec238e01f51397b3b653c93b077d9b1bfe8715bb895f20/ruff-0.15.16-py3-none-macosx_11_0_arm64.whl", hash = "sha256:3a39fec45ab316cc23e7558f23fea4a70403ddb5648ea9a4a3854a16973d0071", size = 10421345, upload-time = "2026-06-04T16:32:37.251Z" },
|
{ url = "https://files.pythonhosted.org/packages/fe/93/78d462e7d39968e58094dc57be7d09ffb14ce37da5b68ed70338a35a1f21/ruff-0.15.19-py3-none-macosx_11_0_arm64.whl", hash = "sha256:5a2c86ba6870dd415a9d9eb8be94d7924ebec6a26ffc7958ec7ca29d4bff967d", size = 10641416, upload-time = "2026-06-24T01:10:48.923Z" },
|
||||||
{ url = "https://files.pythonhosted.org/packages/b0/c2/cc7fad3ec9169373f5b6a18f1917b91080feec40c3f9658334a1d28e2f03/ruff-0.15.16-py3-none-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:ba93191d79003116b95128c9d306e045200fdbd0bccb782b110f3cd1d4abc5cf", size = 10757217, upload-time = "2026-06-04T16:32:54.722Z" },
|
{ url = "https://files.pythonhosted.org/packages/76/c4/5cb66cfd1f865d5cca908b86c93ac785e7f572193d3c7426079ca6643e24/ruff-0.15.19-py3-none-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:82b432bc087264aea70fd25ac198918b70bd9e2aa0db4297b0bb91bbfbbc63ce", size = 11015582, upload-time = "2026-06-24T01:10:30.089Z" },
|
||||||
{ url = "https://files.pythonhosted.org/packages/69/d2/3474009eaa0a65b31fa7152a2fad5e2f050c640ceb1e6b02ee6922e94c82/ruff-0.15.16-py3-none-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:c6ee4b90520630120ef032aa5cc10db483852dff950e78b1d717e2993a61ac8d", size = 10507035, upload-time = "2026-06-04T16:33:05.343Z" },
|
{ url = "https://files.pythonhosted.org/packages/51/9f/8ecfaec10cf5eecd28fbc00ff4fb867db90a1be54bf3d39ebf93f893cd52/ruff-0.15.19-py3-none-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:8530a09d03b3a8c994f8b559a7dcdabc690bcd3f78ef276c38c83166798ebf56", size = 10744059, upload-time = "2026-06-24T01:10:32.48Z" },
|
||||||
{ url = "https://files.pythonhosted.org/packages/ca/81/b7ae6ccbd11f0c8dc3d5d67fc4be9b57ff57ca86ba56152021378e1277f2/ruff-0.15.16-py3-none-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:4e4215bc938bc3c8215c1472c1aa437e310fee20cd427335fec9d7e609563628", size = 11255291, upload-time = "2026-06-04T16:32:49.49Z" },
|
{ url = "https://files.pythonhosted.org/packages/35/6b/983249d04562bc2d590edd75f32455cdb473affb3ba4bc8d883e939c697d/ruff-0.15.19-py3-none-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:87bf21fb3875fe69f0eacc825411657e2e85589cce633c35c0adf1113649c62b", size = 11568461, upload-time = "2026-06-24T01:10:17.435Z" },
|
||||||
{ url = "https://files.pythonhosted.org/packages/d9/e1/46e526f1a7cc90857ce6ddf25fbb77eb6568651ac38d71b033af07076dd5/ruff-0.15.16-py3-none-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:7c8d26be963b090f10e29abc8b3e74a2a321f6fa34e02424e30b5af89350ecbb", size = 12124922, upload-time = "2026-06-04T16:33:07.821Z" },
|
{ url = "https://files.pythonhosted.org/packages/eb/39/bc7794f127b18f492a3b4ee82bba5a900c985ff13b72b46f46e3c171ba34/ruff-0.15.19-py3-none-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:f9b229cb3ef56ecc2c1c8ebeca64b7a7740ccaef40a9eb097e78dde5a8560b83", size = 12429690, upload-time = "2026-06-24T01:10:40.638Z" },
|
||||||
{ url = "https://files.pythonhosted.org/packages/1a/da/5c791b088b596b24d0deb967fa28ae02ad751a140c0b9ea81c5ab915d6c0/ruff-0.15.16-py3-none-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:f198cf4123602a2280ed46c307bcbafe41758d6fee5b456b6b6058ca1514b3b4", size = 11332186, upload-time = "2026-06-04T16:33:02.971Z" },
|
{ url = "https://files.pythonhosted.org/packages/0a/3b/0de6859e698ed11c8a49e765196c8d333599b6a546c0715df39b6ba1aa2e/ruff-0.15.19-py3-none-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:c6c754515be7b76afe6e7e62df7776709571bcfc1631183828afcf3bafa869e3", size = 11693067, upload-time = "2026-06-24T01:10:25.681Z" },
|
||||||
{ url = "https://files.pythonhosted.org/packages/72/11/5da87abe20047c8962361473923ebb2f62b595250126aadfad8c20649c1e/ruff-0.15.16-py3-none-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:bb27515fa6240fb586ae82b901a59e67d24acff86f2190b433dc542fe0435aeb", size = 11373541, upload-time = "2026-06-04T16:32:47.007Z" },
|
{ url = "https://files.pythonhosted.org/packages/89/3d/0b1f30f84bee9ae6ae8d349c2ba8b6f4b040966744efdd3acc804ae7c024/ruff-0.15.19-py3-none-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:6a498f82e0f4d8904c4e0aea5139cdfac1f39d19a3c51d491292f63a36e83b2e", size = 11616911, upload-time = "2026-06-24T01:10:44.809Z" },
|
||||||
{ url = "https://files.pythonhosted.org/packages/fe/2a/8554754c23a854ae3fd6b507e36ad61ddb121e298c6d5d617dec94ed0f14/ruff-0.15.16-py3-none-manylinux_2_31_riscv64.whl", hash = "sha256:a267c46ba1593fc26b8eecbea050b39d40c0b6bb7781ee11c90a02cd10032951", size = 11353014, upload-time = "2026-06-04T16:32:34.795Z" },
|
{ url = "https://files.pythonhosted.org/packages/4d/eb/c90bd3dfc12eed9032c2c1bfe05105b93a1b2c8bce555db6308315b853ce/ruff-0.15.19-py3-none-manylinux_2_31_riscv64.whl", hash = "sha256:d48caa34488fb521fd0ef4aea2b0e8fe758298df044138f0d67b687a6a0d07ed", size = 11649343, upload-time = "2026-06-24T01:10:23.472Z" },
|
||||||
{ url = "https://files.pythonhosted.org/packages/62/25/62ea41529ec89f742ea3fed9cb1059c72877ec7cf9b9e99ac9cf3294d1d9/ruff-0.15.16-py3-none-musllinux_1_2_aarch64.whl", hash = "sha256:528c68f39a91498a8d50e91ff5985df3d105782bab49cc378e73ac26bff083e8", size = 10737467, upload-time = "2026-06-04T16:32:26.348Z" },
|
{ url = "https://files.pythonhosted.org/packages/82/91/01caa13602a2f12fae5edbe8caf78b3c1e6db1293132aee6959eecce095c/ruff-0.15.19-py3-none-musllinux_1_2_aarch64.whl", hash = "sha256:4171b6613effa9363cd46dd4f75bd1827b6d1b946b5e278ed0c600d305379445", size = 10977610, upload-time = "2026-06-24T01:10:50.892Z" },
|
||||||
{ url = "https://files.pythonhosted.org/packages/90/17/334d3ad9de4d40f9dd58fdd09e35ce64553bb501e2f19a839e2fb6be14fc/ruff-0.15.16-py3-none-musllinux_1_2_armv7l.whl", hash = "sha256:7ed55c58950df60589a9a7a5d2f8fa5f54ebd287163be805adfe6ee95a9de123", size = 10521910, upload-time = "2026-06-04T16:32:32.54Z" },
|
{ url = "https://files.pythonhosted.org/packages/3c/51/acb817922feab9ecbb3201377d4dbe7a25f1395e46545820061973f03468/ruff-0.15.19-py3-none-musllinux_1_2_armv7l.whl", hash = "sha256:27c15b2a241dd4d995557949a094fe78b8ad99122a38ccae1595849bcc947b3f", size = 10744900, upload-time = "2026-06-24T01:10:42.726Z" },
|
||||||
{ url = "https://files.pythonhosted.org/packages/4d/bd/3ac7c6ae77a885c1004b3dda2446ea401768d24f851c14b4ad4b24f6639c/ruff-0.15.16-py3-none-musllinux_1_2_i686.whl", hash = "sha256:d482feaf51512b50f9790ceb417a56a61dd1e9d9bf967662b9ed27c01b34f53a", size = 10979190, upload-time = "2026-06-04T16:32:57.492Z" },
|
{ url = "https://files.pythonhosted.org/packages/84/bc/5c8ca46b8a7a3f2b16cfbec88721d772b1c93912904e8f8c2e49470fea63/ruff-0.15.19-py3-none-musllinux_1_2_i686.whl", hash = "sha256:ed03b7862d68f0a8771d50ee129980cbf1b113f96e250b73954bc292f689e0bb", size = 11293560, upload-time = "2026-06-24T01:10:21.262Z" },
|
||||||
{ url = "https://files.pythonhosted.org/packages/33/d7/609546e6a413c3f216fbf2a50c928f97c80939154f6a0503114094a86191/ruff-0.15.16-py3-none-musllinux_1_2_x86_64.whl", hash = "sha256:1e15bc8c94513dae2a40cc9ef07c94fdd4ecc9e29dabebeebe170f952322c9e3", size = 11477014, upload-time = "2026-06-04T16:32:44.687Z" },
|
{ url = "https://files.pythonhosted.org/packages/81/e0/4a888cbe4d5523b3f77a2b1fa043f46cfeba1b32eac35dcfadee0578fa8a/ruff-0.15.19-py3-none-musllinux_1_2_x86_64.whl", hash = "sha256:08143f0685ae278b30727ea72e90c61e5bd9c31b91aac4f5bb989538f73d24b8", size = 11696533, upload-time = "2026-06-24T01:10:53.046Z" },
|
||||||
{ url = "https://files.pythonhosted.org/packages/74/0d/f2cd247ad32633a5c36e97141a2c21b11c6279f7957bc2ff360b1e08fddd/ruff-0.15.16-py3-none-win32.whl", hash = "sha256:580378f7bd4aa25f72e74aa54948a9622f142b1e509521dd10902e886681cc1e", size = 10735541, upload-time = "2026-06-04T16:32:30.145Z" },
|
{ url = "https://files.pythonhosted.org/packages/98/43/c34b2fcd79262a85161764a97aaca89c3e4f574340ab61430cefa2bdd2c1/ruff-0.15.19-py3-none-win32.whl", hash = "sha256:8f47f0f92952af2557212bb10cf3e695cd4cf28b2c6e42cdb18ec6c9ebfa19da", size = 10986299, upload-time = "2026-06-24T01:10:55.185Z" },
|
||||||
{ url = "https://files.pythonhosted.org/packages/8b/9e/02e845ef151b1dee585e55c4739f8e1734ae1d9f1221dff65761c162208b/ruff-0.15.16-py3-none-win_amd64.whl", hash = "sha256:408256017284eddf98fff77b29aa4fb30f586042d535b2d9befc6512f400aaec", size = 11843403, upload-time = "2026-06-04T16:32:39.76Z" },
|
{ url = "https://files.pythonhosted.org/packages/22/e8/15fd23e02b2442b56b2026b455977bc3057aa34b26e6323d1e99e8531a9f/ruff-0.15.19-py3-none-win_amd64.whl", hash = "sha256:efeca47ee3f9d4a7162655a3b8e6ee4a878646044233978d4d2c1ff8cdd914f0", size = 12123473, upload-time = "2026-06-24T01:10:27.74Z" },
|
||||||
{ url = "https://files.pythonhosted.org/packages/15/19/016553f86f207450aebebc2b2b5088d086b901cc8186c02ac4284db3bd88/ruff-0.15.16-py3-none-win_arm64.whl", hash = "sha256:8cd61783afb39638a7133ef0d2dfb1e91277593962f81b5a8423eb0b888a6121", size = 11134555, upload-time = "2026-06-04T16:33:00.136Z" },
|
{ url = "https://files.pythonhosted.org/packages/30/66/9a73695e31eaee04f35d8475998bf8ab354465f9c638936d76111603dcc5/ruff-0.15.19-py3-none-win_arm64.whl", hash = "sha256:6c6b607466e47349332eb1d9be52fb1467423fc07c217341af41cd0f3f0573be", size = 11376779, upload-time = "2026-06-24T01:10:34.465Z" },
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "sentry-sdk"
|
name = "sentry-sdk"
|
||||||
version = "2.61.1"
|
version = "2.63.0"
|
||||||
source = { registry = "https://pypi.org/simple" }
|
source = { registry = "https://pypi.org/simple" }
|
||||||
dependencies = [
|
dependencies = [
|
||||||
{ name = "certifi" },
|
{ name = "certifi" },
|
||||||
{ name = "urllib3" },
|
{ name = "urllib3" },
|
||||||
]
|
]
|
||||||
sdist = { url = "https://files.pythonhosted.org/packages/63/3b/4bc6b348bbd331daa14d4babe9f2b99bc854f4da41560eefb9488d78481d/sentry_sdk-2.61.1.tar.gz", hash = "sha256:9c6adccb3feefa9ba032c8d295ca477575c2f11896046a2b0ad686c47c4af555", size = 459429, upload-time = "2026-06-01T07:24:18.875Z" }
|
sdist = { url = "https://files.pythonhosted.org/packages/ba/c8/b3c970a5b186722d276cd40a05b3254e03bccc0208560aff20f612e018e8/sentry_sdk-2.63.0.tar.gz", hash = "sha256:2a1502bf864769275dbc8c2c9fc7a0f7f5e18358180b615d262d13a31ffba216", size = 912449, upload-time = "2026-06-16T12:45:57.553Z" }
|
||||||
wheels = [
|
wheels = [
|
||||||
{ url = "https://files.pythonhosted.org/packages/df/54/c9218db183846e08efaf68534889ef42e499dde432778881104a42f7071b/sentry_sdk-2.61.1-py3-none-any.whl", hash = "sha256:fa36eaf4b8ad708f718500d4bdcc1532637526a22beb874d88cbc0a46458b5ae", size = 483735, upload-time = "2026-06-01T07:24:17.027Z" },
|
{ url = "https://files.pythonhosted.org/packages/7b/57/cb205f7d93373120f666b9c5736dc0815524d96a9b278e7a728f018dc22a/sentry_sdk-2.63.0-py3-none-any.whl", hash = "sha256:3a9b5ddd403f79eb73bd670f75f04485819db53d28f76ced7bc09041cb0dfd6a", size = 495950, upload-time = "2026-06-16T12:45:55.819Z" },
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
@@ -2077,6 +2115,7 @@ name = "sith"
|
|||||||
version = "3"
|
version = "3"
|
||||||
source = { editable = "." }
|
source = { editable = "." }
|
||||||
dependencies = [
|
dependencies = [
|
||||||
|
{ name = "aemark" },
|
||||||
{ name = "celery", extra = ["redis"] },
|
{ name = "celery", extra = ["redis"] },
|
||||||
{ name = "cryptography" },
|
{ name = "cryptography" },
|
||||||
{ name = "dict2xml" },
|
{ name = "dict2xml" },
|
||||||
@@ -2098,7 +2137,6 @@ dependencies = [
|
|||||||
{ name = "ical", version = "13.2.5", source = { registry = "https://pypi.org/simple" }, marker = "python_full_version >= '3.13'" },
|
{ name = "ical", version = "13.2.5", source = { registry = "https://pypi.org/simple" }, marker = "python_full_version >= '3.13'" },
|
||||||
{ name = "jinja2" },
|
{ name = "jinja2" },
|
||||||
{ name = "libsass" },
|
{ name = "libsass" },
|
||||||
{ name = "mistune" },
|
|
||||||
{ name = "phonenumbers" },
|
{ name = "phonenumbers" },
|
||||||
{ name = "pillow" },
|
{ name = "pillow" },
|
||||||
{ name = "psutil" },
|
{ name = "psutil" },
|
||||||
@@ -2145,36 +2183,36 @@ tests = [
|
|||||||
|
|
||||||
[package.metadata]
|
[package.metadata]
|
||||||
requires-dist = [
|
requires-dist = [
|
||||||
|
{ name = "aemark", specifier = ">=0.1.1" },
|
||||||
{ name = "celery", extras = ["redis"], specifier = ">=5.6.3,<8" },
|
{ name = "celery", extras = ["redis"], specifier = ">=5.6.3,<8" },
|
||||||
{ name = "cryptography", specifier = ">=48.0.0,<49.0.0" },
|
{ name = "cryptography", specifier = ">=49.0.0,<50.0.0" },
|
||||||
{ name = "dict2xml", specifier = ">=1.7.8,<2.0.0" },
|
{ name = "dict2xml", specifier = ">=1.7.8,<2.0.0" },
|
||||||
{ name = "django", specifier = ">=5.2.15,<6.0.0" },
|
{ name = "django", specifier = ">=5.2.15,<6.0.0" },
|
||||||
{ name = "django-celery-beat", specifier = ">=2.9.0" },
|
{ name = "django-celery-beat", specifier = ">=2.9.0" },
|
||||||
{ name = "django-celery-results", specifier = ">=2.6.0" },
|
{ name = "django-celery-results", specifier = ">=2.6.0" },
|
||||||
{ name = "django-countries", specifier = ">=8.2.0,<9.0.0" },
|
{ name = "django-countries", specifier = ">=9.0.0,<10.0.0" },
|
||||||
{ name = "django-haystack", specifier = ">=3.4.0,<4.0.0" },
|
{ name = "django-haystack", specifier = ">=3.4.0,<4.0.0" },
|
||||||
{ name = "django-honeypot", specifier = ">=1.3.0,<2" },
|
{ name = "django-honeypot", specifier = ">=1.3.0,<2" },
|
||||||
{ name = "django-jinja", specifier = ">=2.11.0,<3.0.0" },
|
{ name = "django-jinja", specifier = ">=2.11.0,<3.0.0" },
|
||||||
{ name = "django-ninja", specifier = ">=1.6.2,<2.0.0" },
|
{ name = "django-ninja", specifier = ">=1.6.2,<2.0.0" },
|
||||||
{ name = "django-ninja-extra", specifier = ">=0.31.4" },
|
{ name = "django-ninja-extra", specifier = ">=0.31.5" },
|
||||||
{ name = "django-ordered-model", specifier = ">=3.7.4,<4.0.0" },
|
{ name = "django-ordered-model", specifier = ">=3.7.4,<4.0.0" },
|
||||||
{ name = "django-phonenumber-field", specifier = ">=8.4.0,<9.0.0" },
|
{ name = "django-phonenumber-field", specifier = ">=8.4.0,<9.0.0" },
|
||||||
{ name = "django-simple-captcha", specifier = ">=0.6.3,<1.0.0" },
|
{ name = "django-simple-captcha", specifier = ">=0.6.3,<1.0.0" },
|
||||||
{ name = "environs", extras = ["django"], specifier = ">=6.0.5,<16" },
|
{ name = "environs", extras = ["django"], specifier = ">=15.0.1,<16" },
|
||||||
{ name = "honcho", specifier = ">=2.0.0" },
|
{ name = "honcho", specifier = ">=2.0.0" },
|
||||||
{ name = "ical", specifier = ">=12.0.0,<14.0.0" },
|
{ name = "ical", specifier = ">=12.0.0,<14.0.0" },
|
||||||
{ name = "jinja2", specifier = ">=3.1.6,<4.0.0" },
|
{ name = "jinja2", specifier = ">=3.1.6,<4.0.0" },
|
||||||
{ name = "libsass", specifier = ">=0.23.0,<1.0.0" },
|
{ name = "libsass", specifier = ">=0.23.0,<1.0.0" },
|
||||||
{ name = "mistune", specifier = ">=3.2.1,<4.0.0" },
|
{ name = "phonenumbers", specifier = ">=9.0.33,<10.0.0" },
|
||||||
{ name = "phonenumbers", specifier = ">=9.0.32,<10.0.0" },
|
|
||||||
{ name = "pillow", specifier = ">=12.2.0,<13.0.0" },
|
{ name = "pillow", specifier = ">=12.2.0,<13.0.0" },
|
||||||
{ name = "psutil", specifier = ">=7.2.2,<8.0.0" },
|
{ name = "psutil", specifier = ">=7.2.2,<8.0.0" },
|
||||||
{ name = "pydantic-extra-types", specifier = ">=2.11.1,<3.0.0" },
|
{ name = "pydantic-extra-types", specifier = ">=2.11.1,<3.0.0" },
|
||||||
{ name = "python-dateutil", specifier = ">=2.9.0.post0,<3.0.0.0" },
|
{ name = "python-dateutil", specifier = ">=2.9.0.post0,<3.0.0.0" },
|
||||||
{ name = "redis", extras = ["hiredis"], specifier = ">=3.4.0,<8.0.0" },
|
{ name = "redis", extras = ["hiredis"], specifier = ">=6.4.0,<9.0.0" },
|
||||||
{ name = "reportlab", specifier = ">=4.5.1,<5.0.0" },
|
{ name = "reportlab", specifier = ">=5.0.0,<6.0.0" },
|
||||||
{ name = "requests", specifier = ">=2.34.2,<3.0.0" },
|
{ name = "requests", specifier = ">=2.34.2,<3.0.0" },
|
||||||
{ name = "sentry-sdk", specifier = ">=2.61.1,<3.0.0" },
|
{ name = "sentry-sdk", specifier = ">=2.63.0,<3.0.0" },
|
||||||
{ name = "sphinx", specifier = ">=9.1.0,<10" },
|
{ name = "sphinx", specifier = ">=9.1.0,<10" },
|
||||||
{ name = "tomli", specifier = ">=2.4.1,<3.0.0" },
|
{ name = "tomli", specifier = ">=2.4.1,<3.0.0" },
|
||||||
{ name = "xapian-haystack", specifier = ">=4.0.0,<5.0.0" },
|
{ name = "xapian-haystack", specifier = ">=4.0.0,<5.0.0" },
|
||||||
@@ -2182,13 +2220,13 @@ requires-dist = [
|
|||||||
|
|
||||||
[package.metadata.requires-dev]
|
[package.metadata.requires-dev]
|
||||||
dev = [
|
dev = [
|
||||||
{ name = "django-debug-toolbar", specifier = ">=6.3.0,<7" },
|
{ name = "django-debug-toolbar", specifier = ">=7.0.0,<8" },
|
||||||
{ name = "djhtml", specifier = ">=3.0.11,<4.0.0" },
|
{ name = "djhtml", specifier = ">=3.0.11,<4.0.0" },
|
||||||
{ name = "faker", specifier = ">=40.21.0,<41.0.0" },
|
{ name = "faker", specifier = ">=40.23.0,<41.0.0" },
|
||||||
{ name = "ipython", specifier = ">=9.14.1,<10.0.0" },
|
{ name = "ipython", specifier = ">=9.14.1,<10.0.0" },
|
||||||
{ name = "pre-commit", specifier = ">=4.6.0,<5.0.0" },
|
{ name = "pre-commit", specifier = ">=4.6.0,<5.0.0" },
|
||||||
{ name = "rjsmin", specifier = ">=1.2.5,<2.0.0" },
|
{ name = "rjsmin", specifier = ">=1.2.5,<2.0.0" },
|
||||||
{ name = "ruff", specifier = ">=0.15.16,<1.0.0" },
|
{ name = "ruff", specifier = ">=0.15.19,<1.0.0" },
|
||||||
]
|
]
|
||||||
docs = [
|
docs = [
|
||||||
{ name = "mkdocs", specifier = ">=1.6.1,<2.0.0" },
|
{ name = "mkdocs", specifier = ">=1.6.1,<2.0.0" },
|
||||||
@@ -2199,11 +2237,11 @@ docs = [
|
|||||||
]
|
]
|
||||||
prod = [{ name = "psycopg", extras = ["c"], specifier = ">=3.3.4,<4.0.0" }]
|
prod = [{ name = "psycopg", extras = ["c"], specifier = ">=3.3.4,<4.0.0" }]
|
||||||
tests = [
|
tests = [
|
||||||
{ name = "beautifulsoup4", specifier = ">=4.14.3,<5" },
|
{ name = "beautifulsoup4", specifier = ">=4.15.0,<5" },
|
||||||
{ name = "freezegun", specifier = ">=1.5.5,<2.0.0" },
|
{ name = "freezegun", specifier = ">=1.5.5,<2.0.0" },
|
||||||
{ name = "lxml", specifier = ">=6.1.1,<7" },
|
{ name = "lxml", specifier = ">=6.1.1,<7" },
|
||||||
{ name = "model-bakery", specifier = ">=1.23.4,<2.0.0" },
|
{ name = "model-bakery", specifier = ">=1.24.0,<2.0.0" },
|
||||||
{ name = "pytest", specifier = ">=9.0.3,<10.0.0" },
|
{ name = "pytest", specifier = ">=9.1.1,<10.0.0" },
|
||||||
{ name = "pytest-cov", specifier = ">=7.1.0,<8.0.0" },
|
{ name = "pytest-cov", specifier = ">=7.1.0,<8.0.0" },
|
||||||
{ name = "pytest-django", specifier = ">=4.12.0,<5.0.0" },
|
{ name = "pytest-django", specifier = ">=4.12.0,<5.0.0" },
|
||||||
]
|
]
|
||||||
@@ -2426,14 +2464,14 @@ wheels = [
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "tzlocal"
|
name = "tzlocal"
|
||||||
version = "5.3.1"
|
version = "5.4.3"
|
||||||
source = { registry = "https://pypi.org/simple" }
|
source = { registry = "https://pypi.org/simple" }
|
||||||
dependencies = [
|
dependencies = [
|
||||||
{ name = "tzdata", marker = "sys_platform == 'win32'" },
|
{ name = "tzdata", marker = "sys_platform == 'win32'" },
|
||||||
]
|
]
|
||||||
sdist = { url = "https://files.pythonhosted.org/packages/8b/2e/c14812d3d4d9cd1773c6be938f89e5735a1f11a9f184ac3639b93cef35d5/tzlocal-5.3.1.tar.gz", hash = "sha256:cceffc7edecefea1f595541dbd6e990cb1ea3d19bf01b2809f362a03dd7921fd", size = 30761, upload-time = "2025-03-05T21:17:41.549Z" }
|
sdist = { url = "https://files.pythonhosted.org/packages/48/55/15e2340963d2bfedcc6042da3911438fd336f8ae96b65bdbe3a29766da0c/tzlocal-5.4.3.tar.gz", hash = "sha256:3a8c9bc18cf47e1dcde252ea0e6a72a6cde320a400b6ac6db1f1f8cccd553c00", size = 30873, upload-time = "2026-06-17T04:17:41.764Z" }
|
||||||
wheels = [
|
wheels = [
|
||||||
{ url = "https://files.pythonhosted.org/packages/c2/14/e2a54fabd4f08cd7af1c07030603c3356b74da07f7cc056e600436edfa17/tzlocal-5.3.1-py3-none-any.whl", hash = "sha256:eb1a66c3ef5847adf7a834f1be0800581b683b5608e74f86ecbcef8ab91bb85d", size = 18026, upload-time = "2025-03-05T21:17:39.857Z" },
|
{ url = "https://files.pythonhosted.org/packages/42/28/fc144409c71569e928585f8f3c629d80d1ca3ef40175e9222f01588f98c9/tzlocal-5.4.3-py3-none-any.whl", hash = "sha256:24ce97bb58e2a973f7640ec2553ab4e6f6d5a0d0d1aa9dc43bca21d89e1feb82", size = 18039, upload-time = "2026-06-17T04:17:40.027Z" },
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
@@ -2456,7 +2494,7 @@ wheels = [
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "virtualenv"
|
name = "virtualenv"
|
||||||
version = "21.4.2"
|
version = "21.5.1"
|
||||||
source = { registry = "https://pypi.org/simple" }
|
source = { registry = "https://pypi.org/simple" }
|
||||||
dependencies = [
|
dependencies = [
|
||||||
{ name = "distlib" },
|
{ name = "distlib" },
|
||||||
@@ -2464,9 +2502,9 @@ dependencies = [
|
|||||||
{ name = "platformdirs" },
|
{ name = "platformdirs" },
|
||||||
{ name = "python-discovery" },
|
{ name = "python-discovery" },
|
||||||
]
|
]
|
||||||
sdist = { url = "https://files.pythonhosted.org/packages/e1/0d/4e93c8e6d1001a75763f87d8f5ecda8ebc7f4aa2153dddfaf4ae8892821a/virtualenv-21.4.2.tar.gz", hash = "sha256:38e6ee0a555615c0ea9da2ac7e9998fe8dc3b911dd33ad8eaad2020957653b0c", size = 7613326, upload-time = "2026-05-31T17:01:22.827Z" }
|
sdist = { url = "https://files.pythonhosted.org/packages/f1/a5/81f987504738e6defeed61ec1c47e2aefab3c35d8eeb87e1b3f38cf28254/virtualenv-21.5.1.tar.gz", hash = "sha256:dca3bf98275a59c652b69d68e73433e597d977c2da9198882479d1a7188009c8", size = 4578798, upload-time = "2026-06-16T16:23:58.603Z" }
|
||||||
wheels = [
|
wheels = [
|
||||||
{ url = "https://files.pythonhosted.org/packages/bf/c4/557dc082be035381b85fdb2b74e21d3d21b57750b74f2b47a32f3a639ff9/virtualenv-21.4.2-py3-none-any.whl", hash = "sha256:854210ca524a1a4d0d744734f4acbc721c3ffe163b85bbf5d56d14d5ae2f0fae", size = 7594079, upload-time = "2026-05-31T17:01:20.735Z" },
|
{ url = "https://files.pythonhosted.org/packages/2c/02/3623e6169bed617ed1e2d372f7c69f92ec28d54c4dfc997055c8578ec148/virtualenv-21.5.1-py3-none-any.whl", hash = "sha256:55aa670b67bbfb991b03fda39bd3276d92c419d702376e98c5df1c9989a26783", size = 4558820, upload-time = "2026-06-16T16:23:56.963Z" },
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
@@ -2507,11 +2545,11 @@ wheels = [
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "wcwidth"
|
name = "wcwidth"
|
||||||
version = "0.7.0"
|
version = "0.8.1"
|
||||||
source = { registry = "https://pypi.org/simple" }
|
source = { registry = "https://pypi.org/simple" }
|
||||||
sdist = { url = "https://files.pythonhosted.org/packages/2c/ee/afaf0f85a9a18fe47a67f1e4422ed6cf1fe642f0ae0a2f81166231303c52/wcwidth-0.7.0.tar.gz", hash = "sha256:90e3a7ea092341c44b99562e75d09e4d5160fe7a3974c6fb842a101a95e7eed0", size = 182132, upload-time = "2026-05-02T16:04:12.653Z" }
|
sdist = { url = "https://files.pythonhosted.org/packages/49/b4/51fe890511f0f242d07cb1ebe6a5b6db417262b9d2568b460347c57d95cc/wcwidth-0.8.1.tar.gz", hash = "sha256:faf5b4a5366a72dc49cad48cdf21f52bdf63bdda995178e483ba247ff79089b9", size = 1466072, upload-time = "2026-06-08T05:57:23.146Z" }
|
||||||
wheels = [
|
wheels = [
|
||||||
{ url = "https://files.pythonhosted.org/packages/41/52/e465037f5375f43533d1a80b6923955201596a99142ed524d77b571a1418/wcwidth-0.7.0-py3-none-any.whl", hash = "sha256:5d69154c429a82910e241c738cd0e2976fac8a2dd47a1a805f4afed1c0f136f2", size = 110825, upload-time = "2026-05-02T16:04:11.033Z" },
|
{ url = "https://files.pythonhosted.org/packages/bd/6e/95b0e537de1f4d4301f76f944642c6da50d1511cc7b3d64dc418a66c7509/wcwidth-0.8.1-py3-none-any.whl", hash = "sha256:f453740b1e4a4f3291faa37944c555d71056c4da08d59809b307ef4feba695c8", size = 323092, upload-time = "2026-06-08T05:57:21.413Z" },
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
|
|||||||
Reference in New Issue
Block a user