Merge pull request #714 from ae-utbm/taiste

More ruff rules, mistune update and more bot-blocking features
This commit is contained in:
thomas girod 2024-07-11 11:47:45 +02:00 committed by GitHub
commit b852176958
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
276 changed files with 2449 additions and 2549 deletions

View File

@ -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.4.10 rev: v0.5.1
hooks: hooks:
- id: ruff # just check the code, and print the errors - id: ruff # just check the code, and print the errors
- id: ruff # actually fix the fixable errors, but print nothing - id: ruff # actually fix the fixable errors, but print nothing

View File

@ -1,4 +1,3 @@
# -*- coding:utf-8 -*
# #
# Copyright 2023 © AE UTBM # Copyright 2023 © AE UTBM
# ae@utbm.fr / ae.info@utbm.fr # ae@utbm.fr / ae.info@utbm.fr

View File

@ -1,4 +1,3 @@
# -*- coding:utf-8 -*
# #
# Copyright 2023 © AE UTBM # Copyright 2023 © AE UTBM
# ae@utbm.fr / ae.info@utbm.fr # ae@utbm.fr / ae.info@utbm.fr

View File

@ -1,4 +1,3 @@
# -*- coding: utf-8 -*-
from __future__ import unicode_literals from __future__ import unicode_literals
import django.core.validators import django.core.validators

View File

@ -1,4 +1,3 @@
# -*- coding: utf-8 -*-
from __future__ import unicode_literals from __future__ import unicode_literals
import django.db.models.deletion import django.db.models.deletion
@ -101,6 +100,6 @@ class Migration(migrations.Migration):
), ),
), ),
migrations.AlterUniqueTogether( migrations.AlterUniqueTogether(
name="operation", unique_together=set([("number", "journal")]) name="operation", unique_together={("number", "journal")}
), ),
] ]

View File

@ -1,4 +1,3 @@
# -*- coding: utf-8 -*-
from __future__ import unicode_literals from __future__ import unicode_literals
import phonenumber_field.modelfields import phonenumber_field.modelfields

View File

@ -1,4 +1,3 @@
# -*- coding: utf-8 -*-
from __future__ import unicode_literals from __future__ import unicode_literals
import django.db.models.deletion import django.db.models.deletion
@ -46,6 +45,6 @@ class Migration(migrations.Migration):
), ),
), ),
migrations.AlterUniqueTogether( migrations.AlterUniqueTogether(
name="label", unique_together=set([("name", "club_account")]) name="label", unique_together={("name", "club_account")}
), ),
] ]

View File

@ -1,4 +1,3 @@
# -*- coding: utf-8 -*-
from __future__ import unicode_literals from __future__ import unicode_literals
from django.db import migrations, models from django.db import migrations, models

View File

@ -1,4 +1,3 @@
# -*- coding:utf-8 -*
# #
# Copyright 2023 © AE UTBM # Copyright 2023 © AE UTBM
# ae@utbm.fr / ae.info@utbm.fr # ae@utbm.fr / ae.info@utbm.fr
@ -37,11 +36,11 @@ class CurrencyField(models.DecimalField):
def __init__(self, *args, **kwargs): def __init__(self, *args, **kwargs):
kwargs["max_digits"] = 12 kwargs["max_digits"] = 12
kwargs["decimal_places"] = 2 kwargs["decimal_places"] = 2
super(CurrencyField, self).__init__(*args, **kwargs) super().__init__(*args, **kwargs)
def to_python(self, value): def to_python(self, value):
try: try:
return super(CurrencyField, self).to_python(value).quantize(Decimal("0.01")) return super().to_python(value).quantize(Decimal("0.01"))
except AttributeError: except AttributeError:
return None return None
@ -62,6 +61,15 @@ class Company(models.Model):
class Meta: class Meta:
verbose_name = _("company") verbose_name = _("company")
def __str__(self):
return self.name
def get_absolute_url(self):
return reverse("accounting:co_edit", kwargs={"co_id": self.id})
def get_display_name(self):
return self.name
def is_owned_by(self, user): def is_owned_by(self, user):
""" """
Method to see if that object can be edited by the given user Method to see if that object can be edited by the given user
@ -88,15 +96,6 @@ class Company(models.Model):
return True return True
return False return False
def get_absolute_url(self):
return reverse("accounting:co_edit", kwargs={"co_id": self.id})
def get_display_name(self):
return self.name
def __str__(self):
return self.name
class BankAccount(models.Model): class BankAccount(models.Model):
name = models.CharField(_("name"), max_length=30) name = models.CharField(_("name"), max_length=30)
@ -113,6 +112,12 @@ class BankAccount(models.Model):
verbose_name = _("Bank account") verbose_name = _("Bank account")
ordering = ["club", "name"] ordering = ["club", "name"]
def __str__(self):
return self.name
def get_absolute_url(self):
return reverse("accounting:bank_details", kwargs={"b_account_id": self.id})
def is_owned_by(self, user): def is_owned_by(self, user):
""" """
Method to see if that object can be edited by the given user Method to see if that object can be edited by the given user
@ -126,12 +131,6 @@ class BankAccount(models.Model):
return True return True
return False return False
def get_absolute_url(self):
return reverse("accounting:bank_details", kwargs={"b_account_id": self.id})
def __str__(self):
return self.name
class ClubAccount(models.Model): class ClubAccount(models.Model):
name = models.CharField(_("name"), max_length=30) name = models.CharField(_("name"), max_length=30)
@ -152,6 +151,12 @@ class ClubAccount(models.Model):
verbose_name = _("Club account") verbose_name = _("Club account")
ordering = ["bank_account", "name"] ordering = ["bank_account", "name"]
def __str__(self):
return self.name
def get_absolute_url(self):
return reverse("accounting:club_details", kwargs={"c_account_id": self.id})
def is_owned_by(self, user): def is_owned_by(self, user):
""" """
Method to see if that object can be edited by the given user Method to see if that object can be edited by the given user
@ -189,12 +194,6 @@ class ClubAccount(models.Model):
def get_open_journal(self): def get_open_journal(self):
return self.journals.filter(closed=False).first() return self.journals.filter(closed=False).first()
def get_absolute_url(self):
return reverse("accounting:club_details", kwargs={"c_account_id": self.id})
def __str__(self):
return self.name
def get_display_name(self): def get_display_name(self):
return _("%(club_account)s on %(bank_account)s") % { return _("%(club_account)s on %(bank_account)s") % {
"club_account": self.name, "club_account": self.name,
@ -225,6 +224,12 @@ class GeneralJournal(models.Model):
verbose_name = _("General journal") verbose_name = _("General journal")
ordering = ["-start_date"] ordering = ["-start_date"]
def __str__(self):
return self.name
def get_absolute_url(self):
return reverse("accounting:journal_details", kwargs={"j_id": self.id})
def is_owned_by(self, user): def is_owned_by(self, user):
""" """
Method to see if that object can be edited by the given user Method to see if that object can be edited by the given user
@ -250,12 +255,6 @@ class GeneralJournal(models.Model):
def can_be_viewed_by(self, user): def can_be_viewed_by(self, user):
return self.club_account.can_be_viewed_by(user) return self.club_account.can_be_viewed_by(user)
def get_absolute_url(self):
return reverse("accounting:journal_details", kwargs={"j_id": self.id})
def __str__(self):
return self.name
def update_amounts(self): def update_amounts(self):
self.amount = 0 self.amount = 0
self.effective_amount = 0 self.effective_amount = 0
@ -357,6 +356,18 @@ class Operation(models.Model):
unique_together = ("number", "journal") unique_together = ("number", "journal")
ordering = ["-number"] ordering = ["-number"]
def __str__(self):
return f"{self.amount} € | {self.date} | {self.accounting_type} | {self.done}"
def save(self, *args, **kwargs):
if self.number is None:
self.number = self.journal.operations.count() + 1
super().save(*args, **kwargs)
self.journal.update_amounts()
def get_absolute_url(self):
return reverse("accounting:journal_details", kwargs={"j_id": self.journal.id})
def __getattribute__(self, attr): def __getattribute__(self, attr):
if attr == "target": if attr == "target":
return self.get_target() return self.get_target()
@ -364,7 +375,7 @@ class Operation(models.Model):
return object.__getattribute__(self, attr) return object.__getattribute__(self, attr)
def clean(self): def clean(self):
super(Operation, self).clean() super().clean()
if self.date is None: if self.date is None:
raise ValidationError(_("The date must be set.")) raise ValidationError(_("The date must be set."))
elif self.date < self.journal.start_date: elif self.date < self.journal.start_date:
@ -410,12 +421,6 @@ class Operation(models.Model):
tar = Company.objects.filter(id=self.target_id).first() tar = Company.objects.filter(id=self.target_id).first()
return tar return tar
def save(self):
if self.number is None:
self.number = self.journal.operations.count() + 1
super(Operation, self).save()
self.journal.update_amounts()
def is_owned_by(self, user): def is_owned_by(self, user):
""" """
Method to see if that object can be edited by the given user Method to see if that object can be edited by the given user
@ -444,17 +449,6 @@ class Operation(models.Model):
return True return True
return False return False
def get_absolute_url(self):
return reverse("accounting:journal_details", kwargs={"j_id": self.journal.id})
def __str__(self):
return "%d € | %s | %s | %s" % (
self.amount,
self.date,
self.accounting_type,
self.done,
)
class AccountingType(models.Model): class AccountingType(models.Model):
""" """
@ -487,6 +481,12 @@ class AccountingType(models.Model):
verbose_name = _("accounting type") verbose_name = _("accounting type")
ordering = ["movement_type", "code"] ordering = ["movement_type", "code"]
def __str__(self):
return self.code + " - " + self.get_movement_type_display() + " - " + self.label
def get_absolute_url(self):
return reverse("accounting:type_list")
def is_owned_by(self, user): def is_owned_by(self, user):
""" """
Method to see if that object can be edited by the given user Method to see if that object can be edited by the given user
@ -497,12 +497,6 @@ class AccountingType(models.Model):
return True return True
return False return False
def get_absolute_url(self):
return reverse("accounting:type_list")
def __str__(self):
return self.code + " - " + self.get_movement_type_display() + " - " + self.label
class SimplifiedAccountingType(models.Model): class SimplifiedAccountingType(models.Model):
""" """
@ -521,6 +515,15 @@ class SimplifiedAccountingType(models.Model):
verbose_name = _("simplified type") verbose_name = _("simplified type")
ordering = ["accounting_type__movement_type", "accounting_type__code"] ordering = ["accounting_type__movement_type", "accounting_type__code"]
def __str__(self):
return (
f"{self.get_movement_type_display()} "
f"- {self.accounting_type.code} - {self.label}"
)
def get_absolute_url(self):
return reverse("accounting:simple_type_list")
@property @property
def movement_type(self): def movement_type(self):
return self.accounting_type.movement_type return self.accounting_type.movement_type
@ -528,18 +531,6 @@ class SimplifiedAccountingType(models.Model):
def get_movement_type_display(self): def get_movement_type_display(self):
return self.accounting_type.get_movement_type_display() return self.accounting_type.get_movement_type_display()
def get_absolute_url(self):
return reverse("accounting:simple_type_list")
def __str__(self):
return (
self.get_movement_type_display()
+ " - "
+ self.accounting_type.code
+ " - "
+ self.label
)
class Label(models.Model): class Label(models.Model):
"""Label allow a club to sort its operations""" """Label allow a club to sort its operations"""

View File

@ -1,4 +1,3 @@
# -*- coding:utf-8 -*
# #
# Copyright 2023 © AE UTBM # Copyright 2023 © AE UTBM
# ae@utbm.fr / ae.info@utbm.fr # ae@utbm.fr / ae.info@utbm.fr

View File

@ -1,4 +1,3 @@
# -*- coding:utf-8 -*
# #
# Copyright 2023 © AE UTBM # Copyright 2023 © AE UTBM
# ae@utbm.fr / ae.info@utbm.fr # ae@utbm.fr / ae.info@utbm.fr

View File

@ -1,4 +1,3 @@
# -*- coding:utf-8 -*
# #
# Copyright 2023 © AE UTBM # Copyright 2023 © AE UTBM
# ae@utbm.fr / ae.info@utbm.fr # ae@utbm.fr / ae.info@utbm.fr
@ -210,7 +209,7 @@ class ClubAccountCreateView(CanCreateMixin, CreateView):
template_name = "core/create.jinja" template_name = "core/create.jinja"
def get_initial(self): def get_initial(self):
ret = super(ClubAccountCreateView, self).get_initial() ret = super().get_initial()
if "parent" in self.request.GET.keys(): if "parent" in self.request.GET.keys():
obj = BankAccount.objects.filter(id=int(self.request.GET["parent"])).first() obj = BankAccount.objects.filter(id=int(self.request.GET["parent"])).first()
if obj is not None: if obj is not None:
@ -296,7 +295,7 @@ class JournalCreateView(CanCreateMixin, CreateView):
template_name = "core/create.jinja" template_name = "core/create.jinja"
def get_initial(self): def get_initial(self):
ret = super(JournalCreateView, self).get_initial() ret = super().get_initial()
if "parent" in self.request.GET.keys(): if "parent" in self.request.GET.keys():
obj = ClubAccount.objects.filter(id=int(self.request.GET["parent"])).first() obj = ClubAccount.objects.filter(id=int(self.request.GET["parent"])).first()
if obj is not None: if obj is not None:
@ -339,7 +338,7 @@ class JournalDeleteView(CanEditPropMixin, DeleteView):
def dispatch(self, request, *args, **kwargs): def dispatch(self, request, *args, **kwargs):
self.object = self.get_object() self.object = self.get_object()
if self.object.operations.count() == 0: if self.object.operations.count() == 0:
return super(JournalDeleteView, self).dispatch(request, *args, **kwargs) return super().dispatch(request, *args, **kwargs)
else: else:
raise PermissionDenied raise PermissionDenied
@ -387,7 +386,7 @@ class OperationForm(forms.ModelForm):
def __init__(self, *args, **kwargs): def __init__(self, *args, **kwargs):
club_account = kwargs.pop("club_account", None) club_account = kwargs.pop("club_account", None)
super(OperationForm, self).__init__(*args, **kwargs) super().__init__(*args, **kwargs)
if club_account: if club_account:
self.fields["label"].queryset = club_account.labels.order_by("name").all() self.fields["label"].queryset = club_account.labels.order_by("name").all()
if self.instance.target_type == "USER": if self.instance.target_type == "USER":
@ -400,7 +399,7 @@ class OperationForm(forms.ModelForm):
self.fields["company"].initial = self.instance.target_id self.fields["company"].initial = self.instance.target_id
def clean(self): def clean(self):
self.cleaned_data = super(OperationForm, self).clean() self.cleaned_data = super().clean()
if "target_type" in self.cleaned_data.keys(): if "target_type" in self.cleaned_data.keys():
if ( if (
self.cleaned_data.get("user") is None self.cleaned_data.get("user") is None
@ -430,7 +429,7 @@ class OperationForm(forms.ModelForm):
return self.cleaned_data return self.cleaned_data
def save(self): def save(self):
ret = super(OperationForm, self).save() ret = super().save()
if ( if (
self.instance.target_type == "ACCOUNT" self.instance.target_type == "ACCOUNT"
and not self.instance.linked_operation and not self.instance.linked_operation
@ -482,14 +481,14 @@ class OperationCreateView(CanCreateMixin, CreateView):
return self.form_class(club_account=ca, **self.get_form_kwargs()) return self.form_class(club_account=ca, **self.get_form_kwargs())
def get_initial(self): def get_initial(self):
ret = super(OperationCreateView, self).get_initial() ret = super().get_initial()
if self.journal is not None: if self.journal is not None:
ret["journal"] = self.journal.id ret["journal"] = self.journal.id
return ret return ret
def get_context_data(self, **kwargs): def get_context_data(self, **kwargs):
"""Add journal to the context""" """Add journal to the context"""
kwargs = super(OperationCreateView, self).get_context_data(**kwargs) kwargs = super().get_context_data(**kwargs)
if self.journal: if self.journal:
kwargs["object"] = self.journal kwargs["object"] = self.journal
return kwargs return kwargs
@ -507,7 +506,7 @@ class OperationEditView(CanEditMixin, UpdateView):
def get_context_data(self, **kwargs): def get_context_data(self, **kwargs):
"""Add journal to the context""" """Add journal to the context"""
kwargs = super(OperationEditView, self).get_context_data(**kwargs) kwargs = super().get_context_data(**kwargs)
kwargs["object"] = self.object.journal kwargs["object"] = self.object.journal
return kwargs return kwargs
@ -683,16 +682,16 @@ class JournalNatureStatementView(JournalTabsMixin, CanViewMixin, DetailView):
for sat in [None] + list( for sat in [None] + list(
SimplifiedAccountingType.objects.order_by("label").all() SimplifiedAccountingType.objects.order_by("label").all()
): ):
sum = queryset.filter( amount = queryset.filter(
accounting_type__movement_type=movement_type, simpleaccounting_type=sat accounting_type__movement_type=movement_type, simpleaccounting_type=sat
).aggregate(amount_sum=Sum("amount"))["amount_sum"] ).aggregate(amount_sum=Sum("amount"))["amount_sum"]
if sat: if sat:
sat = sat.label sat = sat.label
else: else:
sat = "" sat = ""
if sum: if amount:
total_sum += sum total_sum += amount
statement[sat] = sum statement[sat] = amount
ret[movement_type] = statement ret[movement_type] = statement
ret[movement_type + "_sum"] = total_sum ret[movement_type + "_sum"] = total_sum
return ret return ret
@ -728,7 +727,7 @@ class JournalNatureStatementView(JournalTabsMixin, CanViewMixin, DetailView):
def get_context_data(self, **kwargs): def get_context_data(self, **kwargs):
"""Add infos to the context""" """Add infos to the context"""
kwargs = super(JournalNatureStatementView, self).get_context_data(**kwargs) kwargs = super().get_context_data(**kwargs)
kwargs["statement"] = self.big_statement() kwargs["statement"] = self.big_statement()
return kwargs return kwargs
@ -767,7 +766,7 @@ class JournalPersonStatementView(JournalTabsMixin, CanViewMixin, DetailView):
def get_context_data(self, **kwargs): def get_context_data(self, **kwargs):
"""Add journal to the context""" """Add journal to the context"""
kwargs = super(JournalPersonStatementView, self).get_context_data(**kwargs) kwargs = super().get_context_data(**kwargs)
kwargs["credit_statement"] = self.statement("CREDIT") kwargs["credit_statement"] = self.statement("CREDIT")
kwargs["debit_statement"] = self.statement("DEBIT") kwargs["debit_statement"] = self.statement("DEBIT")
kwargs["total_credit"] = self.total("CREDIT") kwargs["total_credit"] = self.total("CREDIT")
@ -797,7 +796,7 @@ class JournalAccountingStatementView(JournalTabsMixin, CanViewMixin, DetailView)
def get_context_data(self, **kwargs): def get_context_data(self, **kwargs):
"""Add journal to the context""" """Add journal to the context"""
kwargs = super(JournalAccountingStatementView, self).get_context_data(**kwargs) kwargs = super().get_context_data(**kwargs)
kwargs["statement"] = self.statement() kwargs["statement"] = self.statement()
return kwargs return kwargs
@ -852,7 +851,7 @@ class LabelCreateView(
template_name = "core/create.jinja" template_name = "core/create.jinja"
def get_initial(self): def get_initial(self):
ret = super(LabelCreateView, self).get_initial() ret = super().get_initial()
if "parent" in self.request.GET.keys(): if "parent" in self.request.GET.keys():
obj = ClubAccount.objects.filter(id=int(self.request.GET["parent"])).first() obj = ClubAccount.objects.filter(id=int(self.request.GET["parent"])).first()
if obj is not None: if obj is not None:
@ -897,19 +896,19 @@ class RefoundAccountView(FormView):
raise PermissionDenied raise PermissionDenied
def dispatch(self, request, *arg, **kwargs): def dispatch(self, request, *arg, **kwargs):
res = super(RefoundAccountView, self).dispatch(request, *arg, **kwargs) res = super().dispatch(request, *arg, **kwargs)
if self.permission(request.user): if self.permission(request.user):
return res return res
def post(self, request, *arg, **kwargs): def post(self, request, *arg, **kwargs):
self.operator = request.user self.operator = request.user
if self.permission(request.user): if self.permission(request.user):
return super(RefoundAccountView, self).post(self, request, *arg, **kwargs) return super().post(self, request, *arg, **kwargs)
def form_valid(self, form): def form_valid(self, form):
self.customer = form.cleaned_data["user"] self.customer = form.cleaned_data["user"]
self.create_selling() self.create_selling()
return super(RefoundAccountView, self).form_valid(form) return super().form_valid(form)
def get_success_url(self): def get_success_url(self):
return reverse("accounting:refound_account") return reverse("accounting:refound_account")

View File

@ -1,4 +1,3 @@
# -*- coding:utf-8 -*
# #
# Copyright 2023 © AE UTBM # Copyright 2023 © AE UTBM
# ae@utbm.fr / ae.info@utbm.fr # ae@utbm.fr / ae.info@utbm.fr

View File

@ -1,4 +1,3 @@
# -*- coding:utf-8 -*
# #
# Copyright 2023 © AE UTBM # Copyright 2023 © AE UTBM
# ae@utbm.fr / ae.info@utbm.fr # ae@utbm.fr / ae.info@utbm.fr

View File

@ -1,4 +1,3 @@
# -*- coding:utf-8 -*
# #
# Copyright 2023 © AE UTBM # Copyright 2023 © AE UTBM
# ae@utbm.fr / ae.info@utbm.fr # ae@utbm.fr / ae.info@utbm.fr

View File

@ -1,4 +1,3 @@
# -*- coding:utf-8 -*
# #
# Copyright 2023 © AE UTBM # Copyright 2023 © AE UTBM
# ae@utbm.fr / ae.info@utbm.fr # ae@utbm.fr / ae.info@utbm.fr

View File

@ -1,4 +1,3 @@
# -*- coding:utf-8 -*
# #
# Copyright 2023 © AE UTBM # Copyright 2023 © AE UTBM
# ae@utbm.fr / ae.info@utbm.fr # ae@utbm.fr / ae.info@utbm.fr

View File

@ -1,4 +1,3 @@
# -*- coding:utf-8 -*
# #
# Copyright 2023 © AE UTBM # Copyright 2023 © AE UTBM
# ae@utbm.fr / ae.info@utbm.fr # ae@utbm.fr / ae.info@utbm.fr
@ -50,7 +49,7 @@ class ManageModelMixin:
class RightModelViewSet(ManageModelMixin, viewsets.ModelViewSet): class RightModelViewSet(ManageModelMixin, viewsets.ModelViewSet):
def dispatch(self, request, *arg, **kwargs): def dispatch(self, request, *arg, **kwargs):
res = super(RightModelViewSet, self).dispatch(request, *arg, **kwargs) res = super().dispatch(request, *arg, **kwargs)
obj = self.queryset obj = self.queryset
user = self.request.user user = self.request.user
try: try:

View File

@ -1,4 +1,3 @@
# -*- coding:utf-8 -*
# #
# Copyright 2023 © AE UTBM # Copyright 2023 © AE UTBM
# ae@utbm.fr / ae.info@utbm.fr # ae@utbm.fr / ae.info@utbm.fr

View File

@ -1,4 +1,3 @@
# -*- coding:utf-8 -*
# #
# Copyright 2023 © AE UTBM # Copyright 2023 © AE UTBM
# ae@utbm.fr / ae.info@utbm.fr # ae@utbm.fr / ae.info@utbm.fr

View File

@ -1,4 +1,3 @@
# -*- coding:utf-8 -*
# #
# Copyright 2023 © AE UTBM # Copyright 2023 © AE UTBM
# ae@utbm.fr / ae.info@utbm.fr # ae@utbm.fr / ae.info@utbm.fr

View File

@ -1,4 +1,3 @@
# -*- coding:utf-8 -*
# #
# Copyright 2023 © AE UTBM # Copyright 2023 © AE UTBM
# ae@utbm.fr / ae.info@utbm.fr # ae@utbm.fr / ae.info@utbm.fr

View File

@ -1,4 +1,3 @@
# -*- coding:utf-8 -*
# #
# Copyright 2023 © AE UTBM # Copyright 2023 © AE UTBM
# ae@utbm.fr / ae.info@utbm.fr # ae@utbm.fr / ae.info@utbm.fr

View File

@ -1,4 +1,3 @@
# -*- coding:utf-8 -*
# #
# Copyright 2023 © AE UTBM # Copyright 2023 © AE UTBM
# ae@utbm.fr / ae.info@utbm.fr # ae@utbm.fr / ae.info@utbm.fr

View File

@ -1,4 +1,3 @@
# -*- coding:utf-8 -*
# #
# Copyright 2023 © AE UTBM # Copyright 2023 © AE UTBM
# ae@utbm.fr / ae.info@utbm.fr # ae@utbm.fr / ae.info@utbm.fr

View File

@ -1,4 +1,3 @@
# -*- coding:utf-8 -*
# #
# Copyright 2023 © AE UTBM # Copyright 2023 © AE UTBM
# ae@utbm.fr / ae.info@utbm.fr # ae@utbm.fr / ae.info@utbm.fr

View File

@ -1,4 +1,3 @@
# -*- coding:utf-8 -*
# #
# Copyright 2016,2017 # Copyright 2016,2017
# - Skia <skia@libskia.so> # - Skia <skia@libskia.so>
@ -40,7 +39,7 @@ class ClubEditForm(forms.ModelForm):
fields = ["address", "logo", "short_description"] fields = ["address", "logo", "short_description"]
def __init__(self, *args, **kwargs): def __init__(self, *args, **kwargs):
super(ClubEditForm, self).__init__(*args, **kwargs) super().__init__(*args, **kwargs)
self.fields["short_description"].widget = forms.Textarea() self.fields["short_description"].widget = forms.Textarea()
@ -61,7 +60,7 @@ class MailingForm(forms.Form):
) )
def __init__(self, club_id, user_id, mailings, *args, **kwargs): def __init__(self, club_id, user_id, mailings, *args, **kwargs):
super(MailingForm, self).__init__(*args, **kwargs) super().__init__(*args, **kwargs)
self.fields["action"] = forms.TypedChoiceField( self.fields["action"] = forms.TypedChoiceField(
choices=( choices=(
@ -116,7 +115,7 @@ class MailingForm(forms.Form):
""" """
Convert given users into real users and check their validity Convert given users into real users and check their validity
""" """
cleaned_data = super(MailingForm, self).clean() cleaned_data = super().clean()
users = [] users = []
for user in cleaned_data["subscription_users"]: for user in cleaned_data["subscription_users"]:
user = User.objects.filter(id=user).first() user = User.objects.filter(id=user).first()
@ -133,7 +132,7 @@ class MailingForm(forms.Form):
return users return users
def clean(self): def clean(self):
cleaned_data = super(MailingForm, self).clean() cleaned_data = super().clean()
if not "action" in cleaned_data: if not "action" in cleaned_data:
# If there is no action provided, we can stop here # If there is no action provided, we can stop here
@ -164,7 +163,7 @@ class SellingsForm(forms.Form):
) )
def __init__(self, club, *args, **kwargs): def __init__(self, club, *args, **kwargs):
super(SellingsForm, self).__init__(*args, **kwargs) super().__init__(*args, **kwargs)
self.fields["products"] = forms.ModelMultipleChoiceField( self.fields["products"] = forms.ModelMultipleChoiceField(
club.products.order_by("name").filter(archived=False).all(), club.products.order_by("name").filter(archived=False).all(),
label=_("Products"), label=_("Products"),
@ -201,7 +200,7 @@ class ClubMemberForm(forms.Form):
self.club.members.filter(end_date=None).order_by("-role").all() self.club.members.filter(end_date=None).order_by("-role").all()
) )
self.request_user_membership = self.club.get_membership_for(self.request_user) self.request_user_membership = self.club.get_membership_for(self.request_user)
super(ClubMemberForm, self).__init__(*args, **kwargs) super().__init__(*args, **kwargs)
# Using a ModelForm binds too much the form with the model and we don't want that # Using a ModelForm binds too much the form with the model and we don't want that
# We want the view to process the model creation since they are multiple users # We want the view to process the model creation since they are multiple users
@ -241,7 +240,7 @@ class ClubMemberForm(forms.Form):
Check that the user is not trying to add an user already in the club Check that the user is not trying to add an user already in the club
Also check that the user is valid and has a valid subscription Also check that the user is valid and has a valid subscription
""" """
cleaned_data = super(ClubMemberForm, self).clean() cleaned_data = super().clean()
users = [] users = []
for user_id in cleaned_data["users"]: for user_id in cleaned_data["users"]:
user = User.objects.filter(id=user_id).first() user = User.objects.filter(id=user_id).first()
@ -264,7 +263,7 @@ class ClubMemberForm(forms.Form):
""" """
Check user rights for adding an user Check user rights for adding an user
""" """
cleaned_data = super(ClubMemberForm, self).clean() cleaned_data = super().clean()
if "start_date" in cleaned_data and not cleaned_data["start_date"]: if "start_date" in cleaned_data and not cleaned_data["start_date"]:
# Drop start_date if allowed to edition but not specified # Drop start_date if allowed to edition but not specified

View File

@ -1,4 +1,3 @@
# -*- coding: utf-8 -*-
from __future__ import unicode_literals from __future__ import unicode_literals
import django.core.validators import django.core.validators

View File

@ -1,4 +1,3 @@
# -*- coding: utf-8 -*-
from __future__ import unicode_literals from __future__ import unicode_literals
import django.db.models.deletion import django.db.models.deletion

View File

@ -1,4 +1,3 @@
# -*- coding: utf-8 -*-
from __future__ import unicode_literals from __future__ import unicode_literals
from django.db import migrations, models from django.db import migrations, models

View File

@ -1,4 +1,3 @@
# -*- coding: utf-8 -*-
from __future__ import unicode_literals from __future__ import unicode_literals
import django.db.models.deletion import django.db.models.deletion

View File

@ -1,4 +1,3 @@
# -*- coding: utf-8 -*-
from __future__ import unicode_literals from __future__ import unicode_literals
import django.db.models.deletion import django.db.models.deletion

View File

@ -1,4 +1,3 @@
# -*- coding: utf-8 -*-
from __future__ import unicode_literals from __future__ import unicode_literals
import django.utils.timezone import django.utils.timezone

View File

@ -1,4 +1,3 @@
# -*- coding: utf-8 -*-
from __future__ import unicode_literals from __future__ import unicode_literals
from django.db import migrations from django.db import migrations

View File

@ -1,4 +1,3 @@
# -*- coding: utf-8 -*-
from __future__ import unicode_literals from __future__ import unicode_literals
from django.db import migrations, models from django.db import migrations, models

View File

@ -1,4 +1,3 @@
# -*- coding: utf-8 -*-
from __future__ import unicode_literals from __future__ import unicode_literals
import re import re
@ -110,6 +109,6 @@ class Migration(migrations.Migration):
), ),
migrations.AlterUniqueTogether( migrations.AlterUniqueTogether(
name="mailingsubscription", name="mailingsubscription",
unique_together=set([("user", "email", "mailing")]), unique_together={("user", "email", "mailing")},
), ),
] ]

View File

@ -1,4 +1,3 @@
# -*- coding: utf-8 -*-
from __future__ import unicode_literals from __future__ import unicode_literals
import django.db.models.deletion import django.db.models.deletion

View File

@ -1,4 +1,3 @@
# -*- coding: utf-8 -*-
from __future__ import unicode_literals from __future__ import unicode_literals
from django.db import migrations, models from django.db import migrations, models

View File

@ -1,4 +1,3 @@
# -*- coding: utf-8 -*-
from __future__ import unicode_literals from __future__ import unicode_literals
import django.db.models.deletion import django.db.models.deletion
@ -16,7 +15,7 @@ class Migration(migrations.Migration):
name="owner_group", name="owner_group",
field=models.ForeignKey( field=models.ForeignKey(
on_delete=django.db.models.deletion.CASCADE, on_delete=django.db.models.deletion.CASCADE,
default=club.models.Club.get_default_owner_group, default=club.models.get_default_owner_group,
related_name="owned_club", related_name="owned_club",
to="core.Group", to="core.Group",
), ),

View File

@ -1,4 +1,3 @@
# -*- coding:utf-8 -*
# #
# Copyright 2016,2017 # Copyright 2016,2017
# - Skia <skia@libskia.so> # - Skia <skia@libskia.so>
@ -41,6 +40,11 @@ from core.models import Group, MetaGroup, Notification, Page, RealGroup, SithFil
# Create your models here. # Create your models here.
# This function prevents generating migration upon settings change
def get_default_owner_group():
return settings.SITH_GROUP_ROOT_ID
class Club(models.Model): class Club(models.Model):
""" """
The Club class, made as a tree to allow nice tidy organization The Club class, made as a tree to allow nice tidy organization
@ -75,10 +79,6 @@ class Club(models.Model):
) )
address = models.CharField(_("address"), max_length=254) address = models.CharField(_("address"), max_length=254)
# This function prevents generating migration upon settings change
def get_default_owner_group():
return settings.SITH_GROUP_ROOT_ID
owner_group = models.ForeignKey( owner_group = models.ForeignKey(
Group, Group,
related_name="owned_club", related_name="owned_club",
@ -106,6 +106,34 @@ class Club(models.Model):
class Meta: class Meta:
ordering = ["name", "unix_name"] ordering = ["name", "unix_name"]
def __str__(self):
return self.name
@transaction.atomic()
def save(self, *args, **kwargs):
old = Club.objects.filter(id=self.id).first()
creation = old is None
if not creation and old.unix_name != self.unix_name:
self._change_unixname(self.unix_name)
super().save(*args, **kwargs)
if creation:
board = MetaGroup(name=self.unix_name + settings.SITH_BOARD_SUFFIX)
board.save()
member = MetaGroup(name=self.unix_name + settings.SITH_MEMBER_SUFFIX)
member.save()
subscribers = Group.objects.filter(
name=settings.SITH_MAIN_MEMBERS_GROUP
).first()
self.make_home()
self.home.edit_groups.set([board])
self.home.view_groups.set([member, subscribers])
self.home.save()
self.make_page()
cache.set(f"sith_club_{self.unix_name}", self)
def get_absolute_url(self):
return reverse("club:club_view", kwargs={"club_id": self.id})
@cached_property @cached_property
def president(self): def president(self):
return self.members.filter( return self.members.filter(
@ -184,28 +212,6 @@ class Club(models.Model):
self.page.parent = self.parent.page self.page.parent = self.parent.page
self.page.save(force_lock=True) self.page.save(force_lock=True)
@transaction.atomic()
def save(self, *args, **kwargs):
old = Club.objects.filter(id=self.id).first()
creation = old is None
if not creation and old.unix_name != self.unix_name:
self._change_unixname(self.unix_name)
super(Club, self).save(*args, **kwargs)
if creation:
board = MetaGroup(name=self.unix_name + settings.SITH_BOARD_SUFFIX)
board.save()
member = MetaGroup(name=self.unix_name + settings.SITH_MEMBER_SUFFIX)
member.save()
subscribers = Group.objects.filter(
name=settings.SITH_MAIN_MEMBERS_GROUP
).first()
self.make_home()
self.home.edit_groups.set([board])
self.home.view_groups.set([member, subscribers])
self.home.save()
self.make_page()
cache.set(f"sith_club_{self.unix_name}", self)
def delete(self, *args, **kwargs): def delete(self, *args, **kwargs):
# Invalidate the cache of this club and of its memberships # Invalidate the cache of this club and of its memberships
for membership in self.members.ongoing().select_related("user"): for membership in self.members.ongoing().select_related("user"):
@ -213,12 +219,6 @@ class Club(models.Model):
cache.delete(f"sith_club_{self.unix_name}") cache.delete(f"sith_club_{self.unix_name}")
super().delete(*args, **kwargs) super().delete(*args, **kwargs)
def __str__(self):
return self.name
def get_absolute_url(self):
return reverse("club:club_view", kwargs={"club_id": self.id})
def get_display_name(self): def get_display_name(self):
return self.name return self.name
@ -374,14 +374,21 @@ class Membership(models.Model):
def __str__(self): def __str__(self):
return ( return (
self.club.name f"{self.club.name} - {self.user.username} "
+ " - " f"- {settings.SITH_CLUB_ROLES[self.role]} "
+ self.user.username f"- {str(_('past member')) if self.end_date is not None else ''}"
+ " - "
+ str(settings.SITH_CLUB_ROLES[self.role])
+ str(" - " + str(_("past member")) if self.end_date is not None else "")
) )
def save(self, *args, **kwargs):
super().save(*args, **kwargs)
if self.end_date is None:
cache.set(f"membership_{self.club_id}_{self.user_id}", self)
else:
cache.set(f"membership_{self.club_id}_{self.user_id}", "not_member")
def get_absolute_url(self):
return reverse("club:club_members", kwargs={"club_id": self.club_id})
def is_owned_by(self, user): def is_owned_by(self, user):
""" """
Method to see if that object can be super edited by the given user Method to see if that object can be super edited by the given user
@ -401,16 +408,6 @@ class Membership(models.Model):
return True return True
return False return False
def get_absolute_url(self):
return reverse("club:club_members", kwargs={"club_id": self.club_id})
def save(self, *args, **kwargs):
super().save(*args, **kwargs)
if self.end_date is None:
cache.set(f"membership_{self.club_id}_{self.user_id}", self)
else:
cache.set(f"membership_{self.club_id}_{self.user_id}", "not_member")
def delete(self, *args, **kwargs): def delete(self, *args, **kwargs):
super().delete(*args, **kwargs) super().delete(*args, **kwargs)
cache.delete(f"membership_{self.club_id}_{self.user_id}") cache.delete(f"membership_{self.club_id}_{self.user_id}")
@ -452,6 +449,26 @@ class Mailing(models.Model):
on_delete=models.CASCADE, on_delete=models.CASCADE,
) )
def __str__(self):
return "%s - %s" % (self.club, self.email_full)
def save(self, *args, **kwargs):
if not self.is_moderated:
for user in (
RealGroup.objects.filter(id=settings.SITH_GROUP_COM_ADMIN_ID)
.first()
.users.all()
):
if not user.notifications.filter(
type="MAILING_MODERATION", viewed=False
).exists():
Notification(
user=user,
url=reverse("com:mailing_admin"),
type="MAILING_MODERATION",
).save(*args, **kwargs)
super().save(*args, **kwargs)
def clean(self): def clean(self):
if Mailing.objects.filter(email=self.email).exists(): if Mailing.objects.filter(email=self.email).exists():
raise ValidationError(_("This mailing list already exists.")) raise ValidationError(_("This mailing list already exists."))
@ -459,7 +476,7 @@ class Mailing(models.Model):
self.is_moderated = True self.is_moderated = True
else: else:
self.moderator = None self.moderator = None
super(Mailing, self).clean() super().clean()
@property @property
def email_full(self): def email_full(self):
@ -481,7 +498,7 @@ class Mailing(models.Model):
def delete(self, *args, **kwargs): def delete(self, *args, **kwargs):
self.subscriptions.all().delete() self.subscriptions.all().delete()
super(Mailing, self).delete() super().delete()
def fetch_format(self): def fetch_format(self):
resp = self.email + ": " resp = self.email + ": "
@ -489,26 +506,6 @@ class Mailing(models.Model):
resp += sub.fetch_format() resp += sub.fetch_format()
return resp return resp
def save(self):
if not self.is_moderated:
for user in (
RealGroup.objects.filter(id=settings.SITH_GROUP_COM_ADMIN_ID)
.first()
.users.all()
):
if not user.notifications.filter(
type="MAILING_MODERATION", viewed=False
).exists():
Notification(
user=user,
url=reverse("com:mailing_admin"),
type="MAILING_MODERATION",
).save()
super(Mailing, self).save()
def __str__(self):
return "%s - %s" % (self.club, self.email_full)
class MailingSubscription(models.Model): class MailingSubscription(models.Model):
""" """
@ -536,6 +533,9 @@ class MailingSubscription(models.Model):
class Meta: class Meta:
unique_together = (("user", "email", "mailing"),) unique_together = (("user", "email", "mailing"),)
def __str__(self):
return "(%s) - %s : %s" % (self.mailing, self.get_username, self.email)
def clean(self): def clean(self):
if not self.user and not self.email: if not self.user and not self.email:
raise ValidationError(_("At least user or email is required")) raise ValidationError(_("At least user or email is required"))
@ -550,7 +550,7 @@ class MailingSubscription(models.Model):
) )
except ObjectDoesNotExist: except ObjectDoesNotExist:
pass pass
super(MailingSubscription, self).clean() super().clean()
def is_owned_by(self, user): def is_owned_by(self, user):
if user.is_anonymous: if user.is_anonymous:
@ -578,6 +578,3 @@ class MailingSubscription(models.Model):
def fetch_format(self): def fetch_format(self):
return self.get_email + " " return self.get_email + " "
def __str__(self):
return "(%s) - %s : %s" % (self.mailing, self.get_username, self.email)

View File

@ -1,4 +1,3 @@
# -*- coding:utf-8 -*
# #
# Copyright 2023 © AE UTBM # Copyright 2023 © AE UTBM
# ae@utbm.fr / ae.info@utbm.fr # ae@utbm.fr / ae.info@utbm.fr

View File

@ -1,4 +1,3 @@
# -*- coding:utf-8 -*
# #
# Copyright 2016,2017 # Copyright 2016,2017
# - Skia <skia@libskia.so> # - Skia <skia@libskia.so>

View File

@ -1,4 +1,3 @@
# -*- coding:utf-8 -*
# #
# Copyright 2016,2017 # Copyright 2016,2017
# - Skia <skia@libskia.so> # - Skia <skia@libskia.so>
@ -195,7 +194,7 @@ class ClubView(ClubTabsMixin, DetailView):
current_tab = "infos" current_tab = "infos"
def get_context_data(self, **kwargs): def get_context_data(self, **kwargs):
kwargs = super(ClubView, self).get_context_data(**kwargs) kwargs = super().get_context_data(**kwargs)
if self.object.page and self.object.page.revisions.exists(): if self.object.page and self.object.page.revisions.exists():
kwargs["page_revision"] = self.object.page.revisions.last().content kwargs["page_revision"] = self.object.page.revisions.last().content
return kwargs return kwargs
@ -209,10 +208,10 @@ class ClubRevView(ClubView):
def dispatch(self, request, *args, **kwargs): def dispatch(self, request, *args, **kwargs):
obj = self.get_object() obj = self.get_object()
self.revision = get_object_or_404(PageRev, pk=kwargs["rev_id"], page__club=obj) self.revision = get_object_or_404(PageRev, pk=kwargs["rev_id"], page__club=obj)
return super(ClubRevView, self).dispatch(request, *args, **kwargs) return super().dispatch(request, *args, **kwargs)
def get_context_data(self, **kwargs): def get_context_data(self, **kwargs):
kwargs = super(ClubRevView, self).get_context_data(**kwargs) kwargs = super().get_context_data(**kwargs)
kwargs["page_revision"] = self.revision.content kwargs["page_revision"] = self.revision.content
return kwargs return kwargs
@ -225,7 +224,7 @@ class ClubPageEditView(ClubTabsMixin, PageEditViewBase):
self.club = get_object_or_404(Club, pk=kwargs["club_id"]) self.club = get_object_or_404(Club, pk=kwargs["club_id"])
if not self.club.page: if not self.club.page:
raise Http404 raise Http404
return super(ClubPageEditView, self).dispatch(request, *args, **kwargs) return super().dispatch(request, *args, **kwargs)
def get_object(self): def get_object(self):
self.page = self.club.page self.page = self.club.page
@ -269,14 +268,14 @@ class ClubMembersView(ClubTabsMixin, CanViewMixin, DetailFormView):
current_tab = "members" current_tab = "members"
def get_form_kwargs(self): def get_form_kwargs(self):
kwargs = super(ClubMembersView, self).get_form_kwargs() kwargs = super().get_form_kwargs()
kwargs["request_user"] = self.request.user kwargs["request_user"] = self.request.user
kwargs["club"] = self.get_object() kwargs["club"] = self.get_object()
kwargs["club_members"] = self.members kwargs["club_members"] = self.members
return kwargs return kwargs
def get_context_data(self, *args, **kwargs): def get_context_data(self, *args, **kwargs):
kwargs = super(ClubMembersView, self).get_context_data(*args, **kwargs) kwargs = super().get_context_data(*args, **kwargs)
kwargs["members"] = self.members kwargs["members"] = self.members
return kwargs return kwargs
@ -284,7 +283,7 @@ class ClubMembersView(ClubTabsMixin, CanViewMixin, DetailFormView):
""" """
Check user rights Check user rights
""" """
resp = super(ClubMembersView, self).form_valid(form) resp = super().form_valid(form)
data = form.clean() data = form.clean()
users = data.pop("users", []) users = data.pop("users", [])
@ -299,7 +298,7 @@ class ClubMembersView(ClubTabsMixin, CanViewMixin, DetailFormView):
def dispatch(self, request, *args, **kwargs): def dispatch(self, request, *args, **kwargs):
self.members = self.get_object().members.ongoing().order_by("-role") self.members = self.get_object().members.ongoing().order_by("-role")
return super(ClubMembersView, self).dispatch(request, *args, **kwargs) return super().dispatch(request, *args, **kwargs)
def get_success_url(self, **kwargs): def get_success_url(self, **kwargs):
return reverse_lazy( return reverse_lazy(
@ -333,12 +332,12 @@ class ClubSellingView(ClubTabsMixin, CanEditMixin, DetailFormView):
def dispatch(self, request, *args, **kwargs): def dispatch(self, request, *args, **kwargs):
try: try:
self.asked_page = int(request.GET.get("page", 1)) self.asked_page = int(request.GET.get("page", 1))
except ValueError: except ValueError as e:
raise Http404 raise Http404 from e
return super(ClubSellingView, self).dispatch(request, *args, **kwargs) return super().dispatch(request, *args, **kwargs)
def get_form_kwargs(self): def get_form_kwargs(self):
kwargs = super(ClubSellingView, self).get_form_kwargs() kwargs = super().get_form_kwargs()
kwargs["club"] = self.object kwargs["club"] = self.object
return kwargs return kwargs
@ -346,7 +345,7 @@ class ClubSellingView(ClubTabsMixin, CanEditMixin, DetailFormView):
return self.get(request, *args, **kwargs) return self.get(request, *args, **kwargs)
def get_context_data(self, **kwargs): def get_context_data(self, **kwargs):
kwargs = super(ClubSellingView, self).get_context_data(**kwargs) kwargs = super().get_context_data(**kwargs)
qs = Selling.objects.filter(club=self.object) qs = Selling.objects.filter(club=self.object)
kwargs["result"] = qs[:0] kwargs["result"] = qs[:0]
@ -390,8 +389,8 @@ class ClubSellingView(ClubTabsMixin, CanEditMixin, DetailFormView):
kwargs["paginator"] = Paginator(kwargs["result"], self.paginate_by) kwargs["paginator"] = Paginator(kwargs["result"], self.paginate_by)
try: try:
kwargs["paginated_result"] = kwargs["paginator"].page(self.asked_page) kwargs["paginated_result"] = kwargs["paginator"].page(self.asked_page)
except InvalidPage: except InvalidPage as e:
raise Http404 raise Http404 from e
return kwargs return kwargs
@ -558,7 +557,7 @@ class ClubStatView(TemplateView):
template_name = "club/stats.jinja" template_name = "club/stats.jinja"
def get_context_data(self, **kwargs): def get_context_data(self, **kwargs):
kwargs = super(ClubStatView, self).get_context_data(**kwargs) kwargs = super().get_context_data(**kwargs)
kwargs["club_list"] = Club.objects.all() kwargs["club_list"] = Club.objects.all()
return kwargs return kwargs
@ -575,7 +574,7 @@ class ClubMailingView(ClubTabsMixin, CanEditMixin, DetailFormView):
current_tab = "mailing" current_tab = "mailing"
def get_form_kwargs(self): def get_form_kwargs(self):
kwargs = super(ClubMailingView, self).get_form_kwargs() kwargs = super().get_form_kwargs()
kwargs["club_id"] = self.get_object().id kwargs["club_id"] = self.get_object().id
kwargs["user_id"] = self.request.user.id kwargs["user_id"] = self.request.user.id
kwargs["mailings"] = self.mailings kwargs["mailings"] = self.mailings
@ -583,10 +582,10 @@ class ClubMailingView(ClubTabsMixin, CanEditMixin, DetailFormView):
def dispatch(self, request, *args, **kwargs): def dispatch(self, request, *args, **kwargs):
self.mailings = Mailing.objects.filter(club_id=self.get_object().id).all() self.mailings = Mailing.objects.filter(club_id=self.get_object().id).all()
return super(ClubMailingView, self).dispatch(request, *args, **kwargs) return super().dispatch(request, *args, **kwargs)
def get_context_data(self, **kwargs): def get_context_data(self, **kwargs):
kwargs = super(ClubMailingView, self).get_context_data(**kwargs) kwargs = super().get_context_data(**kwargs)
kwargs["club"] = self.get_object() kwargs["club"] = self.get_object()
kwargs["user"] = self.request.user kwargs["user"] = self.request.user
kwargs["mailings"] = self.mailings kwargs["mailings"] = self.mailings
@ -670,7 +669,7 @@ class ClubMailingView(ClubTabsMixin, CanEditMixin, DetailFormView):
sub.delete() sub.delete()
def form_valid(self, form): def form_valid(self, form):
resp = super(ClubMailingView, self).form_valid(form) resp = super().form_valid(form)
cleaned_data = form.clean() cleaned_data = form.clean()
error = None error = None
@ -702,7 +701,7 @@ class MailingDeleteView(CanEditMixin, DeleteView):
def dispatch(self, request, *args, **kwargs): def dispatch(self, request, *args, **kwargs):
self.club_id = self.get_object().club.id self.club_id = self.get_object().club.id
return super(MailingDeleteView, self).dispatch(request, *args, **kwargs) return super().dispatch(request, *args, **kwargs)
def get_success_url(self, **kwargs): def get_success_url(self, **kwargs):
if self.redirect_page: if self.redirect_page:
@ -718,9 +717,7 @@ class MailingSubscriptionDeleteView(CanEditMixin, DeleteView):
def dispatch(self, request, *args, **kwargs): def dispatch(self, request, *args, **kwargs):
self.club_id = self.get_object().mailing.club.id self.club_id = self.get_object().mailing.club.id
return super(MailingSubscriptionDeleteView, self).dispatch( return super().dispatch(request, *args, **kwargs)
request, *args, **kwargs
)
def get_success_url(self, **kwargs): def get_success_url(self, **kwargs):
return reverse_lazy("club:mailing", kwargs={"club_id": self.club_id}) return reverse_lazy("club:mailing", kwargs={"club_id": self.club_id})
@ -731,7 +728,7 @@ class MailingAutoGenerationView(View):
self.mailing = get_object_or_404(Mailing, pk=kwargs["mailing_id"]) self.mailing = get_object_or_404(Mailing, pk=kwargs["mailing_id"])
if not request.user.can_edit(self.mailing): if not request.user.can_edit(self.mailing):
raise PermissionDenied raise PermissionDenied
return super(MailingAutoGenerationView, self).dispatch(request, *args, **kwargs) return super().dispatch(request, *args, **kwargs)
def get(self, request, *args, **kwargs): def get(self, request, *args, **kwargs):
club = self.mailing.club club = self.mailing.club
@ -751,7 +748,7 @@ class PosterListView(ClubTabsMixin, PosterListBaseView, CanViewMixin):
return self.club return self.club
def get_context_data(self, **kwargs): def get_context_data(self, **kwargs):
kwargs = super(PosterListView, self).get_context_data(**kwargs) kwargs = super().get_context_data(**kwargs)
kwargs["app"] = "club" kwargs["app"] = "club"
kwargs["club"] = self.club kwargs["club"] = self.club
return kwargs return kwargs
@ -763,7 +760,7 @@ class PosterCreateView(PosterCreateBaseView, CanCreateMixin):
pk_url_kwarg = "club_id" pk_url_kwarg = "club_id"
def get_object(self): def get_object(self):
obj = super(PosterCreateView, self).get_object() obj = super().get_object()
if not obj: if not obj:
return self.club return self.club
return obj return obj
@ -779,7 +776,7 @@ class PosterEditView(ClubTabsMixin, PosterEditBaseView, CanEditMixin):
return reverse_lazy("club:poster_list", kwargs={"club_id": self.club.id}) return reverse_lazy("club:poster_list", kwargs={"club_id": self.club.id})
def get_context_data(self, **kwargs): def get_context_data(self, **kwargs):
kwargs = super(PosterEditView, self).get_context_data(**kwargs) kwargs = super().get_context_data(**kwargs)
kwargs["app"] = "club" kwargs["app"] = "club"
return kwargs return kwargs

View File

@ -1,4 +1,3 @@
# -*- coding:utf-8 -*
# #
# Copyright 2023 © AE UTBM # Copyright 2023 © AE UTBM
# ae@utbm.fr / ae.info@utbm.fr # ae@utbm.fr / ae.info@utbm.fr

View File

@ -1,4 +1,3 @@
# -*- coding:utf-8 -*
# #
# Copyright 2023 © AE UTBM # Copyright 2023 © AE UTBM
# ae@utbm.fr / ae.info@utbm.fr # ae@utbm.fr / ae.info@utbm.fr

View File

@ -1,4 +1,3 @@
# -*- coding: utf-8 -*-
from __future__ import unicode_literals from __future__ import unicode_literals
from django.db import migrations, models from django.db import migrations, models

View File

@ -1,4 +1,3 @@
# -*- coding: utf-8 -*-
from __future__ import unicode_literals from __future__ import unicode_literals
import django.db.models.deletion import django.db.models.deletion

View File

@ -1,4 +1,3 @@
# -*- coding: utf-8 -*-
from __future__ import unicode_literals from __future__ import unicode_literals
import django.db.models.deletion import django.db.models.deletion

View File

@ -1,4 +1,3 @@
# -*- coding: utf-8 -*-
from __future__ import unicode_literals from __future__ import unicode_literals
import django.db.models.deletion import django.db.models.deletion

View File

@ -1,4 +1,3 @@
# -*- coding: utf-8 -*-
from __future__ import unicode_literals from __future__ import unicode_literals
from django.db import migrations, models from django.db import migrations, models

View File

@ -1,4 +1,3 @@
# -*- coding: utf-8 -*-
# Generated by Django 1.11.23 on 2019-08-18 17:00 # Generated by Django 1.11.23 on 2019-08-18 17:00
from __future__ import unicode_literals from __future__ import unicode_literals

View File

@ -1,4 +1,3 @@
# -*- coding:utf-8 -*
# #
# Copyright 2016,2017 # Copyright 2016,2017
# - Skia <skia@libskia.so> # - Skia <skia@libskia.so>
@ -47,14 +46,14 @@ class Sith(models.Model):
weekmail_destinations = models.TextField(_("weekmail destinations"), default="") weekmail_destinations = models.TextField(_("weekmail destinations"), default="")
version = utils.get_git_revision_short_hash() version = utils.get_git_revision_short_hash()
def __str__(self):
return "⛩ Sith ⛩"
def is_owned_by(self, user): def is_owned_by(self, user):
if user.is_anonymous: if user.is_anonymous:
return False return False
return user.is_com_admin return user.is_com_admin
def __str__(self):
return "⛩ Sith ⛩"
NEWS_TYPES = [ NEWS_TYPES = [
("NOTICE", _("Notice")), ("NOTICE", _("Notice")),
@ -91,28 +90,11 @@ class News(models.Model):
on_delete=models.CASCADE, on_delete=models.CASCADE,
) )
def is_owned_by(self, user):
if user.is_anonymous:
return False
return user.is_com_admin or user == self.author
def can_be_edited_by(self, user):
return user.is_com_admin
def can_be_viewed_by(self, user):
return self.is_moderated or user.is_com_admin
def get_absolute_url(self):
return reverse("com:news_detail", kwargs={"news_id": self.id})
def get_full_url(self):
return "https://%s%s" % (settings.SITH_URL, self.get_absolute_url())
def __str__(self): def __str__(self):
return "%s: %s" % (self.type, self.title) return "%s: %s" % (self.type, self.title)
def save(self, *args, **kwargs): def save(self, *args, **kwargs):
super(News, self).save(*args, **kwargs) super().save(*args, **kwargs)
for u in ( for u in (
RealGroup.objects.filter(id=settings.SITH_GROUP_COM_ADMIN_ID) RealGroup.objects.filter(id=settings.SITH_GROUP_COM_ADMIN_ID)
.first() .first()
@ -125,6 +107,23 @@ class News(models.Model):
param="1", param="1",
).save() ).save()
def get_absolute_url(self):
return reverse("com:news_detail", kwargs={"news_id": self.id})
def get_full_url(self):
return "https://%s%s" % (settings.SITH_URL, self.get_absolute_url())
def is_owned_by(self, user):
if user.is_anonymous:
return False
return user.is_com_admin or user == self.author
def can_be_edited_by(self, user):
return user.is_com_admin
def can_be_viewed_by(self, user):
return self.is_moderated or user.is_com_admin
def news_notification_callback(notif): def news_notification_callback(notif):
count = ( count = (
@ -186,6 +185,9 @@ class Weekmail(models.Model):
class Meta: class Meta:
ordering = ["-id"] ordering = ["-id"]
def __str__(self):
return f"Weekmail {self.id} (sent: {self.sent}) - {self.title}"
def send(self): def send(self):
""" """
Send the weekmail to all users with the receive weekmail option opt-in. Send the weekmail to all users with the receive weekmail option opt-in.
@ -241,9 +243,6 @@ class Weekmail(models.Model):
""" """
return "http://" + settings.SITH_URL + static("com/img/weekmail_footerP22.png") return "http://" + settings.SITH_URL + static("com/img/weekmail_footerP22.png")
def __str__(self):
return "Weekmail %s (sent: %s) - %s" % (self.id, self.sent, self.title)
def is_owned_by(self, user): def is_owned_by(self, user):
if user.is_anonymous: if user.is_anonymous:
return False return False
@ -274,18 +273,21 @@ class WeekmailArticle(models.Model):
) )
rank = models.IntegerField(_("rank"), default=-1) rank = models.IntegerField(_("rank"), default=-1)
def __str__(self):
return "%s - %s (%s)" % (self.title, self.author, self.club)
def is_owned_by(self, user): def is_owned_by(self, user):
if user.is_anonymous: if user.is_anonymous:
return False return False
return user.is_com_admin return user.is_com_admin
def __str__(self):
return "%s - %s (%s)" % (self.title, self.author, self.club)
class Screen(models.Model): class Screen(models.Model):
name = models.CharField(_("name"), max_length=128) name = models.CharField(_("name"), max_length=128)
def __str__(self):
return self.name
def active_posters(self): def active_posters(self):
now = timezone.now() now = timezone.now()
return self.posters.filter(is_moderated=True, date_begin__lte=now).filter( return self.posters.filter(is_moderated=True, date_begin__lte=now).filter(
@ -297,9 +299,6 @@ class Screen(models.Model):
return False return False
return user.is_com_admin return user.is_com_admin
def __str__(self):
return "%s" % (self.name)
class Poster(models.Model): class Poster(models.Model):
name = models.CharField( name = models.CharField(
@ -329,6 +328,9 @@ class Poster(models.Model):
on_delete=models.CASCADE, on_delete=models.CASCADE,
) )
def __str__(self):
return self.name
def save(self, *args, **kwargs): def save(self, *args, **kwargs):
if not self.is_moderated: if not self.is_moderated:
for u in ( for u in (
@ -341,7 +343,7 @@ class Poster(models.Model):
url=reverse("com:poster_moderate_list"), url=reverse("com:poster_moderate_list"),
type="POSTER_MODERATION", type="POSTER_MODERATION",
).save() ).save()
return super(Poster, self).save(*args, **kwargs) return super().save(*args, **kwargs)
def clean(self, *args, **kwargs): def clean(self, *args, **kwargs):
if self.date_end and self.date_begin > self.date_end: if self.date_end and self.date_begin > self.date_end:
@ -361,6 +363,3 @@ class Poster(models.Model):
@property @property
def page(self): def page(self):
return self.club.page return self.club.page
def __str__(self):
return self.name

View File

@ -1,4 +1,3 @@
# -*- coding:utf-8 -*
# #
# Copyright 2023 © AE UTBM # Copyright 2023 © AE UTBM
# ae@utbm.fr / ae.info@utbm.fr # ae@utbm.fr / ae.info@utbm.fr

View File

@ -1,4 +1,3 @@
# -*- coding:utf-8 -*
# #
# Copyright 2023 © AE UTBM # Copyright 2023 © AE UTBM
# ae@utbm.fr / ae.info@utbm.fr # ae@utbm.fr / ae.info@utbm.fr

View File

@ -1,4 +1,3 @@
# -*- coding:utf-8 -*
# #
# Copyright 2016,2017 # Copyright 2016,2017
# - Skia <skia@libskia.so> # - Skia <skia@libskia.so>
@ -82,7 +81,7 @@ class PosterForm(forms.ModelForm):
def __init__(self, *args, **kwargs): def __init__(self, *args, **kwargs):
self.user = kwargs.pop("user", None) self.user = kwargs.pop("user", None)
super(PosterForm, self).__init__(*args, **kwargs) super().__init__(*args, **kwargs)
if self.user: if self.user:
if not self.user.is_com_admin: if not self.user.is_com_admin:
self.fields["club"].queryset = Club.objects.filter( self.fields["club"].queryset = Club.objects.filter(
@ -145,7 +144,7 @@ class IsComAdminMixin(View):
def dispatch(self, request, *args, **kwargs): def dispatch(self, request, *args, **kwargs):
if not request.user.is_com_admin: if not request.user.is_com_admin:
raise PermissionDenied raise PermissionDenied
return super(IsComAdminMixin, self).dispatch(request, *args, **kwargs) return super().dispatch(request, *args, **kwargs)
class ComEditView(ComTabsMixin, CanEditPropMixin, UpdateView): class ComEditView(ComTabsMixin, CanEditPropMixin, UpdateView):
@ -199,7 +198,7 @@ class NewsForm(forms.ModelForm):
automoderation = forms.BooleanField(label=_("Automoderation"), required=False) automoderation = forms.BooleanField(label=_("Automoderation"), required=False)
def clean(self): def clean(self):
self.cleaned_data = super(NewsForm, self).clean() self.cleaned_data = super().clean()
if self.cleaned_data["type"] != "NOTICE": if self.cleaned_data["type"] != "NOTICE":
if not self.cleaned_data["start_date"]: if not self.cleaned_data["start_date"]:
self.add_error( self.add_error(
@ -225,7 +224,7 @@ class NewsForm(forms.ModelForm):
return self.cleaned_data return self.cleaned_data
def save(self): def save(self):
ret = super(NewsForm, self).save() ret = super().save()
self.instance.dates.all().delete() self.instance.dates.all().delete()
if self.instance.type == "EVENT" or self.instance.type == "CALL": if self.instance.type == "EVENT" or self.instance.type == "CALL":
NewsDate( NewsDate(
@ -252,24 +251,10 @@ class NewsEditView(CanEditMixin, UpdateView):
pk_url_kwarg = "news_id" pk_url_kwarg = "news_id"
def get_initial(self): def get_initial(self):
init = {} news_date: NewsDate = self.object.dates.order_by("id").first()
try: if news_date is None:
init["start_date"] = ( return {"start_date": None, "end_date": None}
self.object.dates.order_by("id") return {"start_date": news_date.start_date, "end_date": news_date.end_date}
.first()
.start_date.strftime("%Y-%m-%d %H:%M:%S")
)
except:
pass
try:
init["end_date"] = (
self.object.dates.order_by("id")
.first()
.end_date.strftime("%Y-%m-%d %H:%M:%S")
)
except:
pass
return init
def post(self, request, *args, **kwargs): def post(self, request, *args, **kwargs):
form = self.get_form() form = self.get_form()
@ -302,7 +287,7 @@ class NewsEditView(CanEditMixin, UpdateView):
), ),
type="NEWS_MODERATION", type="NEWS_MODERATION",
).save() ).save()
return super(NewsEditView, self).form_valid(form) return super().form_valid(form)
class NewsCreateView(CanCreateMixin, CreateView): class NewsCreateView(CanCreateMixin, CreateView):
@ -312,10 +297,9 @@ class NewsCreateView(CanCreateMixin, CreateView):
def get_initial(self): def get_initial(self):
init = {"author": self.request.user} init = {"author": self.request.user}
try: if "club" not in self.request.GET:
return init
init["club"] = Club.objects.filter(id=self.request.GET["club"]).first() init["club"] = Club.objects.filter(id=self.request.GET["club"]).first()
except:
pass
return init return init
def post(self, request, *args, **kwargs): def post(self, request, *args, **kwargs):
@ -346,7 +330,7 @@ class NewsCreateView(CanCreateMixin, CreateView):
url=reverse("com:news_admin_list"), url=reverse("com:news_admin_list"),
type="NEWS_MODERATION", type="NEWS_MODERATION",
).save() ).save()
return super(NewsCreateView, self).form_valid(form) return super().form_valid(form)
class NewsDeleteView(CanEditMixin, DeleteView): class NewsDeleteView(CanEditMixin, DeleteView):
@ -385,7 +369,7 @@ class NewsListView(CanViewMixin, ListView):
queryset = News.objects.filter(is_moderated=True) queryset = News.objects.filter(is_moderated=True)
def get_context_data(self, **kwargs): def get_context_data(self, **kwargs):
kwargs = super(NewsListView, self).get_context_data(**kwargs) kwargs = super().get_context_data(**kwargs)
kwargs["NewsDate"] = NewsDate kwargs["NewsDate"] = NewsDate
kwargs["timedelta"] = timedelta kwargs["timedelta"] = timedelta
kwargs["birthdays"] = ( kwargs["birthdays"] = (
@ -416,7 +400,7 @@ class WeekmailPreviewView(ComTabsMixin, QuickNotifMixin, CanEditPropMixin, Detai
def dispatch(self, request, *args, **kwargs): def dispatch(self, request, *args, **kwargs):
self.bad_recipients = [] self.bad_recipients = []
return super(WeekmailPreviewView, self).dispatch(request, *args, **kwargs) return super().dispatch(request, *args, **kwargs)
def post(self, request, *args, **kwargs): def post(self, request, *args, **kwargs):
self.object = self.get_object() self.object = self.get_object()
@ -437,14 +421,14 @@ class WeekmailPreviewView(ComTabsMixin, QuickNotifMixin, CanEditPropMixin, Detai
u.preferences.receive_weekmail = False u.preferences.receive_weekmail = False
u.preferences.save() u.preferences.save()
self.quick_notif_list += ["qn_success"] self.quick_notif_list += ["qn_success"]
return super(WeekmailPreviewView, self).get(request, *args, **kwargs) return super().get(request, *args, **kwargs)
def get_object(self, queryset=None): def get_object(self, queryset=None):
return self.model.objects.filter(sent=False).order_by("-id").first() return self.model.objects.filter(sent=False).order_by("-id").first()
def get_context_data(self, **kwargs): def get_context_data(self, **kwargs):
"""Add rendered weekmail""" """Add rendered weekmail"""
kwargs = super(WeekmailPreviewView, self).get_context_data(**kwargs) kwargs = super().get_context_data(**kwargs)
kwargs["weekmail_rendered"] = self.object.render_html() kwargs["weekmail_rendered"] = self.object.render_html()
kwargs["bad_recipients"] = self.bad_recipients kwargs["bad_recipients"] = self.bad_recipients
return kwargs return kwargs
@ -520,11 +504,11 @@ class WeekmailEditView(ComTabsMixin, QuickNotifMixin, CanEditPropMixin, UpdateVi
art.rank = -1 art.rank = -1
art.save() art.save()
self.quick_notif_list += ["qn_success"] self.quick_notif_list += ["qn_success"]
return super(WeekmailEditView, self).get(request, *args, **kwargs) return super().get(request, *args, **kwargs)
def get_context_data(self, **kwargs): def get_context_data(self, **kwargs):
"""Add orphan articles""" """Add orphan articles"""
kwargs = super(WeekmailEditView, self).get_context_data(**kwargs) kwargs = super().get_context_data(**kwargs)
kwargs["orphans"] = WeekmailArticle.objects.filter(weekmail=None) kwargs["orphans"] = WeekmailArticle.objects.filter(weekmail=None)
return kwargs return kwargs
@ -561,22 +545,16 @@ class WeekmailArticleCreateView(QuickNotifMixin, CreateView):
quick_notif_url_arg = "qn_weekmail_new_article" quick_notif_url_arg = "qn_weekmail_new_article"
def get_initial(self): def get_initial(self):
init = {} if "club" not in self.request.GET:
try: return {}
init["club"] = Club.objects.filter(id=self.request.GET["club"]).first() return {"club": Club.objects.filter(id=self.request.GET.get("club")).first()}
except:
pass
return init
def post(self, request, *args, **kwargs): def post(self, request, *args, **kwargs):
form = self.get_form() form = self.get_form()
self.object = form.instance self.object = form.instance
form.is_valid() #  Valid a first time to populate club field form.is_valid() # Valid a first time to populate club field
try:
m = form.instance.club.get_membership_for(request.user) m = form.instance.club.get_membership_for(request.user)
if m.role <= settings.SITH_MAXIMUM_FREE_ROLE: if m is None or m.role <= settings.SITH_MAXIMUM_FREE_ROLE:
raise
except:
form.add_error( form.add_error(
"club", "club",
ValidationError( ValidationError(
@ -592,7 +570,7 @@ class WeekmailArticleCreateView(QuickNotifMixin, CreateView):
def form_valid(self, form): def form_valid(self, form):
form.instance.author = self.request.user form.instance.author = self.request.user
return super(WeekmailArticleCreateView, self).form_valid(form) return super().form_valid(form)
class WeekmailArticleDeleteView(CanEditPropMixin, DeleteView): class WeekmailArticleDeleteView(CanEditPropMixin, DeleteView):
@ -612,10 +590,10 @@ class MailingListAdminView(ComTabsMixin, ListView):
def dispatch(self, request, *args, **kwargs): def dispatch(self, request, *args, **kwargs):
if not (request.user.is_com_admin or request.user.is_root): if not (request.user.is_com_admin or request.user.is_root):
raise PermissionDenied raise PermissionDenied
return super(MailingListAdminView, self).dispatch(request, *args, **kwargs) return super().dispatch(request, *args, **kwargs)
def get_context_data(self, **kwargs): def get_context_data(self, **kwargs):
kwargs = super(MailingListAdminView, self).get_context_data(**kwargs) kwargs = super().get_context_data(**kwargs)
kwargs["moderated"] = self.get_queryset().filter(is_moderated=True).all() kwargs["moderated"] = self.get_queryset().filter(is_moderated=True).all()
kwargs["unmoderated"] = self.get_queryset().filter(is_moderated=False).all() kwargs["unmoderated"] = self.get_queryset().filter(is_moderated=False).all()
kwargs["has_moderated"] = len(kwargs["moderated"]) > 0 kwargs["has_moderated"] = len(kwargs["moderated"]) > 0
@ -647,7 +625,7 @@ class PosterListBaseView(ListView):
self.club = None self.club = None
if club_id: if club_id:
self.club = get_object_or_404(Club, pk=club_id) self.club = get_object_or_404(Club, pk=club_id)
return super(PosterListBaseView, self).dispatch(request, *args, **kwargs) return super().dispatch(request, *args, **kwargs)
def get_queryset(self): def get_queryset(self):
if self.request.user.is_com_admin: if self.request.user.is_com_admin:
@ -656,7 +634,7 @@ class PosterListBaseView(ListView):
return Poster.objects.filter(club=self.club.id) return Poster.objects.filter(club=self.club.id)
def get_context_data(self, **kwargs): def get_context_data(self, **kwargs):
kwargs = super(PosterListBaseView, self).get_context_data(**kwargs) kwargs = super().get_context_data(**kwargs)
if not self.request.user.is_com_admin: if not self.request.user.is_com_admin:
kwargs["club"] = self.club kwargs["club"] = self.club
return kwargs return kwargs
@ -675,15 +653,15 @@ class PosterCreateBaseView(CreateView):
def dispatch(self, request, *args, **kwargs): def dispatch(self, request, *args, **kwargs):
if "club_id" in kwargs: if "club_id" in kwargs:
self.club = get_object_or_404(Club, pk=kwargs["club_id"]) self.club = get_object_or_404(Club, pk=kwargs["club_id"])
return super(PosterCreateBaseView, self).dispatch(request, *args, **kwargs) return super().dispatch(request, *args, **kwargs)
def get_form_kwargs(self): def get_form_kwargs(self):
kwargs = super(PosterCreateBaseView, self).get_form_kwargs() kwargs = super().get_form_kwargs()
kwargs.update({"user": self.request.user}) kwargs.update({"user": self.request.user})
return kwargs return kwargs
def get_context_data(self, **kwargs): def get_context_data(self, **kwargs):
kwargs = super(PosterCreateBaseView, self).get_context_data(**kwargs) kwargs = super().get_context_data(**kwargs)
if not self.request.user.is_com_admin: if not self.request.user.is_com_admin:
kwargs["club"] = self.club kwargs["club"] = self.club
return kwargs return kwargs
@ -691,7 +669,7 @@ class PosterCreateBaseView(CreateView):
def form_valid(self, form): def form_valid(self, form):
if self.request.user.is_com_admin: if self.request.user.is_com_admin:
form.instance.is_moderated = True form.instance.is_moderated = True
return super(PosterCreateBaseView, self).form_valid(form) return super().form_valid(form)
class PosterEditBaseView(UpdateView): class PosterEditBaseView(UpdateView):
@ -718,20 +696,20 @@ class PosterEditBaseView(UpdateView):
if "club_id" in kwargs and kwargs["club_id"]: if "club_id" in kwargs and kwargs["club_id"]:
try: try:
self.club = Club.objects.get(pk=kwargs["club_id"]) self.club = Club.objects.get(pk=kwargs["club_id"])
except Club.DoesNotExist: except Club.DoesNotExist as e:
raise PermissionDenied raise PermissionDenied from e
return super(PosterEditBaseView, self).dispatch(request, *args, **kwargs) return super().dispatch(request, *args, **kwargs)
def get_queryset(self): def get_queryset(self):
return Poster.objects.all() return Poster.objects.all()
def get_form_kwargs(self): def get_form_kwargs(self):
kwargs = super(PosterEditBaseView, self).get_form_kwargs() kwargs = super().get_form_kwargs()
kwargs.update({"user": self.request.user}) kwargs.update({"user": self.request.user})
return kwargs return kwargs
def get_context_data(self, **kwargs): def get_context_data(self, **kwargs):
kwargs = super(PosterEditBaseView, self).get_context_data(**kwargs) kwargs = super().get_context_data(**kwargs)
if hasattr(self, "club"): if hasattr(self, "club"):
kwargs["club"] = self.club kwargs["club"] = self.club
return kwargs return kwargs
@ -739,7 +717,7 @@ class PosterEditBaseView(UpdateView):
def form_valid(self, form): def form_valid(self, form):
if self.request.user.is_com_admin: if self.request.user.is_com_admin:
form.instance.is_moderated = False form.instance.is_moderated = False
return super(PosterEditBaseView, self).form_valid(form) return super().form_valid(form)
class PosterDeleteBaseView(DeleteView): class PosterDeleteBaseView(DeleteView):
@ -754,16 +732,16 @@ class PosterDeleteBaseView(DeleteView):
if "club_id" in kwargs and kwargs["club_id"]: if "club_id" in kwargs and kwargs["club_id"]:
try: try:
self.club = Club.objects.get(pk=kwargs["club_id"]) self.club = Club.objects.get(pk=kwargs["club_id"])
except Club.DoesNotExist: except Club.DoesNotExist as e:
raise PermissionDenied raise PermissionDenied from e
return super(PosterDeleteBaseView, self).dispatch(request, *args, **kwargs) return super().dispatch(request, *args, **kwargs)
class PosterListView(IsComAdminMixin, ComTabsMixin, PosterListBaseView): class PosterListView(IsComAdminMixin, ComTabsMixin, PosterListBaseView):
"""List communication posters""" """List communication posters"""
def get_context_data(self, **kwargs): def get_context_data(self, **kwargs):
kwargs = super(PosterListView, self).get_context_data(**kwargs) kwargs = super().get_context_data(**kwargs)
kwargs["app"] = "com" kwargs["app"] = "com"
return kwargs return kwargs
@ -774,7 +752,7 @@ class PosterCreateView(IsComAdminMixin, ComTabsMixin, PosterCreateBaseView):
success_url = reverse_lazy("com:poster_list") success_url = reverse_lazy("com:poster_list")
def get_context_data(self, **kwargs): def get_context_data(self, **kwargs):
kwargs = super(PosterCreateView, self).get_context_data(**kwargs) kwargs = super().get_context_data(**kwargs)
kwargs["app"] = "com" kwargs["app"] = "com"
return kwargs return kwargs
@ -785,7 +763,7 @@ class PosterEditView(IsComAdminMixin, ComTabsMixin, PosterEditBaseView):
success_url = reverse_lazy("com:poster_list") success_url = reverse_lazy("com:poster_list")
def get_context_data(self, **kwargs): def get_context_data(self, **kwargs):
kwargs = super(PosterEditView, self).get_context_data(**kwargs) kwargs = super().get_context_data(**kwargs)
kwargs["app"] = "com" kwargs["app"] = "com"
return kwargs return kwargs
@ -805,7 +783,7 @@ class PosterModerateListView(IsComAdminMixin, ComTabsMixin, ListView):
queryset = Poster.objects.filter(is_moderated=False).all() queryset = Poster.objects.filter(is_moderated=False).all()
def get_context_data(self, **kwargs): def get_context_data(self, **kwargs):
kwargs = super(PosterModerateListView, self).get_context_data(**kwargs) kwargs = super().get_context_data(**kwargs)
kwargs["app"] = "com" kwargs["app"] = "com"
return kwargs return kwargs
@ -844,7 +822,7 @@ class ScreenSlideshowView(DetailView):
template_name = "com/screen_slideshow.jinja" template_name = "com/screen_slideshow.jinja"
def get_context_data(self, **kwargs): def get_context_data(self, **kwargs):
kwargs = super(ScreenSlideshowView, self).get_context_data(**kwargs) kwargs = super().get_context_data(**kwargs)
kwargs["posters"] = self.object.active_posters() kwargs["posters"] = self.object.active_posters()
return kwargs return kwargs

View File

@ -1,4 +1,3 @@
# -*- coding:utf-8 -*
# #
# Copyright 2023 © AE UTBM # Copyright 2023 © AE UTBM
# ae@utbm.fr / ae.info@utbm.fr # ae@utbm.fr / ae.info@utbm.fr

View File

@ -1,4 +1,3 @@
# -*- coding:utf-8 -*
# #
# Copyright 2023 © AE UTBM # Copyright 2023 © AE UTBM
# ae@utbm.fr / ae.info@utbm.fr # ae@utbm.fr / ae.info@utbm.fr

View File

@ -1,4 +1,3 @@
# -*- coding:utf-8 -*
# #
# Copyright 2017 # Copyright 2017
# - Skia <skia@libskia.so> # - Skia <skia@libskia.so>

View File

@ -1,4 +1,3 @@
# -*- coding:utf-8 -*
# #
# Copyright 2023 © AE UTBM # Copyright 2023 © AE UTBM
# ae@utbm.fr / ae.info@utbm.fr # ae@utbm.fr / ae.info@utbm.fr

View File

@ -1,4 +1,3 @@
# -*- coding:utf-8 -*
# #
# Copyright 2023 © AE UTBM # Copyright 2023 © AE UTBM
# ae@utbm.fr / ae.info@utbm.fr # ae@utbm.fr / ae.info@utbm.fr

View File

@ -1,4 +1,3 @@
# -*- coding:utf-8 -*
# #
# Copyright 2023 © AE UTBM # Copyright 2023 © AE UTBM
# ae@utbm.fr / ae.info@utbm.fr # ae@utbm.fr / ae.info@utbm.fr

View File

@ -24,11 +24,11 @@ class Command(BaseCommand):
def handle(self, *args, **options): def handle(self, *args, **options):
deps = settings.SITH_FRONT_DEP_VERSIONS deps = settings.SITH_FRONT_DEP_VERSIONS
processes = dict( processes = {
(url, create_process(url)) url: create_process(url)
for url in deps.keys() for url in deps.keys()
if parse_semver(deps[url]) is not None if parse_semver(deps[url]) is not None
) }
for url, process in processes.items(): for url, process in processes.items():
try: try:

View File

@ -1,4 +1,3 @@
# -*- coding:utf-8 -*
# #
# Copyright 2018 # Copyright 2018
# - Skia <skia@libskia.so> # - Skia <skia@libskia.so>

View File

@ -1,5 +1,4 @@
#!/usr/bin/env python3 #!/usr/bin/env python3
# -*- coding:utf-8 -*
# #
# Copyright 2019 # Copyright 2019
# - Sli <antoine@bartuccio.fr> # - Sli <antoine@bartuccio.fr>
@ -41,4 +40,4 @@ class Command(compilemessages.Command):
def handle(self, *args, **options): def handle(self, *args, **options):
os.chdir("sith") os.chdir("sith")
super(Command, self).handle(*args, **options) super().handle(*args, **options)

View File

@ -1,5 +1,4 @@
#!/usr/bin/env python3 #!/usr/bin/env python3
# -*- coding:utf-8 -*
# #
# Copyright 2017 # Copyright 2017
# - Sli <antoine@bartuccio.fr> # - Sli <antoine@bartuccio.fr>

View File

@ -1,5 +1,4 @@
#!/usr/bin/env python3 #!/usr/bin/env python3
# -*- coding:utf-8 -*
# #
# Copyright 2019 # Copyright 2019
# - Sli <antoine@bartuccio.fr> # - Sli <antoine@bartuccio.fr>

View File

@ -1,4 +1,3 @@
# -*- coding:utf-8 -*
# #
# Copyright 2024 © AE UTBM # Copyright 2024 © AE UTBM
# ae@utbm.fr / ae.info@utbm.fr # ae@utbm.fr / ae.info@utbm.fr
@ -47,7 +46,7 @@ class Command(BaseCommand):
pyproject = tomli.load(f) pyproject = tomli.load(f)
return pyproject["tool"]["xapian"]["version"] return pyproject["tool"]["xapian"]["version"]
def handle(self, force: bool, *args, **options): def handle(self, *args, force: bool, **options):
if not os.environ.get("VIRTUAL_ENV", None): if not os.environ.get("VIRTUAL_ENV", None):
print("No virtual environment detected, this command can't be used") print("No virtual environment detected, this command can't be used")
return return

View File

@ -1,7 +1,7 @@
#!/usr/bin/env bash #!/usr/bin/env bash
# Originates from https://gist.github.com/jorgecarleitao/ab6246c86c936b9c55fd # Originates from https://gist.github.com/jorgecarleitao/ab6246c86c936b9c55fd
# first argument of the script is Xapian version (e.g. 1.2.19) # first argument of the script is Xapian version (e.g. 1.2.19)
VERSION=$1 VERSION="$1"
# Cleanup env vars for auto discovery mechanism # Cleanup env vars for auto discovery mechanism
export CPATH= export CPATH=

View File

@ -1,4 +1,3 @@
# -*- coding:utf-8 -*
# #
# Copyright 2017 # Copyright 2017
# - Skia <skia@libskia.so> # - Skia <skia@libskia.so>

View File

@ -1,4 +1,3 @@
# -*- coding:utf-8 -*
# #
# Copyright 2016,2017,2023 # Copyright 2016,2017,2023
# - Skia <skia@hya.sk> # - Skia <skia@hya.sk>

View File

@ -1,4 +1,3 @@
# -*- coding:utf-8 -*
# #
# Copyright 2018 # Copyright 2018
# - Skia <skia@libskia.so> # - Skia <skia@libskia.so>

View File

@ -1,4 +1,3 @@
# -*- coding:utf-8 -*
# #
# Copyright 2023 © AE UTBM # Copyright 2023 © AE UTBM
# ae@utbm.fr / ae.info@utbm.fr # ae@utbm.fr / ae.info@utbm.fr

View File

@ -1,4 +1,3 @@
# -*- coding:utf-8 -*
# #
# Copyright 2023 © AE UTBM # Copyright 2023 © AE UTBM
# ae@utbm.fr / ae.info@utbm.fr # ae@utbm.fr / ae.info@utbm.fr
@ -13,163 +12,125 @@
# OR WITHIN THE LOCAL FILE "LICENSE" # OR WITHIN THE LOCAL FILE "LICENSE"
# #
# #
from __future__ import annotations
import os import os
import re import re
from typing import TYPE_CHECKING
import mistune
from django.urls import reverse from django.urls import reverse
from mistune import InlineGrammar, InlineLexer, Markdown, Renderer, escape, escape_link 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"\)" # )
)
class SithRenderer(Renderer): def parse_underline(_inline: InlineParser, m: re.Match, state: InlineState):
def file_link(self, id, suffix): state.append_token({"type": "underline", "raw": m.group("underlined")})
return reverse("core:file_detail", kwargs={"file_id": id}) + suffix return m.end()
def exposant(self, text):
return """<sup>%s</sup>""" % text
def indice(self, text): def underline(md_instance: Markdown):
return """<sub>%s</sub>""" % text md_instance.inline.register(
"underline",
UNDERLINED_RE,
parse_underline,
before="emphasis",
)
md_instance.renderer.register("underline", lambda _, text: f"<u>{text}</u>")
def underline(self, text):
return """<u>%s</u>""" % text
def image(self, original_src, title, text): def parse_sith_link(_inline: InlineParser, m: re.Match, state: InlineState):
"""Rendering a image with title and text. page_name = m.group("page_name")
:param src: source link of the image. page_slug = m.group("page_slug")
:param title: title text of the image. state.append_token(
:param text: alt text of the image. {
""" "type": "link",
style = None "children": [{"type": "text", "raw": page_name}],
if "?" in original_src: "attrs": {"url": reverse("core:page", kwargs={"page_name": page_slug})},
src, params = original_src.rsplit("?", maxsplit=1) }
m = re.search(r"(\d+%?)(x(\d+%?))?", params) )
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: if not m:
src = original_src return super().image(text, url, title)
else:
width = m.group(1) width, height = m.group("width"), m.group("height")
if not width.endswith("%"): if not width.endswith(("%", "px")):
width += "px" width += "px"
style = "width: %s; " % width style = f"width:{width};"
try: if height is not None:
height = m.group(3) if not height.endswith(("%", "px")):
if not height.endswith("%"):
height += "px" height += "px"
style += "height: %s; " % height style += f"height:{height};"
except: return super().image(text, new_url, title).replace("/>", f'style="{style}" />')
pass
else:
params = None
src = original_src
src = escape_link(src)
text = escape(text, quote=True)
if title:
title = escape(title, quote=True)
html = '<img src="%s" alt="%s" title="%s"' % (src, text, title)
else:
html = '<img src="%s" alt="%s"' % (src, text)
if style:
html = '%s style="%s"' % (html, style)
if self.options.get("use_xhtml"):
return "%s />" % html
return "%s>" % html
class SithInlineGrammar(InlineGrammar): markdown = mistune.create_markdown(
double_emphasis = re.compile(r"^\*{2}([\s\S]+?)\*{2}(?!\*)") # **word** renderer=SithRenderer(escape=True),
emphasis = re.compile(r"^\*((?:\*\*|[^\*])+?)\*(?!\*)") # *word* plugins=[
underline = re.compile(r"^_{2}([\s\S]+?)_{2}(?!_)") # __word__ underline,
exposant = re.compile(r"^<sup>([\s\S]+?)</sup>") # <sup>text</sup> sith_link,
indice = re.compile(r"^<sub>([\s\S]+?)</sub>") # <sub>text</sub>
class SithInlineLexer(InlineLexer):
grammar_class = SithInlineGrammar
default_rules = [
"escape",
# 'inline_html',
"autolink",
"url",
"footnote",
"link",
"reflink",
"nolink",
"exposant",
"double_emphasis",
"emphasis",
"underline",
"indice",
"code",
"linebreak",
"strikethrough", "strikethrough",
"text", "footnotes",
] "table",
inline_html_rules = [ "spoiler",
"escape", "subscript",
"autolink", "superscript",
"url", "url",
"link", ],
"reflink", )
"nolink",
"exposant",
"double_emphasis",
"emphasis",
"underline",
"indice",
"code",
"linebreak",
"strikethrough",
"text",
]
def output_underline(self, m):
text = m.group(1)
return self.renderer.underline(text)
def output_exposant(self, m):
text = m.group(1)
return self.renderer.exposant(text)
def output_indice(self, m):
text = m.group(1)
return self.renderer.indice(text)
# Double emphasis rule changed
def output_double_emphasis(self, m):
text = m.group(1)
text = self.output(text)
return self.renderer.double_emphasis(text)
# Emphasis rule changed
def output_emphasis(self, m):
text = m.group(1)
text = self.output(text)
return self.renderer.emphasis(text)
def _process_link(self, m, link, title=None):
try: # Add page:// support for links
page = re.compile(r"^page://(\S*)") # page://nom_de_ma_page
match = page.search(link)
page = match.group(1) or ""
link = reverse("core:page", kwargs={"page_name": page})
except:
pass
try: # Add file:// support for links
file_link = re.compile(r"^file://(\d*)/?(\S*)?") # file://4000/download
match = file_link.search(link)
id = match.group(1)
suffix = match.group(2) or ""
link = reverse("core:file_detail", kwargs={"file_id": id}) + suffix
except:
pass
return super(SithInlineLexer, self)._process_link(m, link, title)
renderer = SithRenderer(escape=True)
inline = SithInlineLexer(renderer)
markdown = Markdown(renderer, inline=inline)
if __name__ == "__main__": if __name__ == "__main__":
root_path = os.path.dirname(os.path.dirname(os.path.abspath(__file__))) root_path = os.path.dirname(os.path.dirname(os.path.abspath(__file__)))

View File

@ -1,4 +1,3 @@
# -*- coding:utf-8 -*
# #
# Copyright 2023 © AE UTBM # Copyright 2023 © AE UTBM
# ae@utbm.fr / ae.info@utbm.fr # ae@utbm.fr / ae.info@utbm.fr
@ -69,5 +68,5 @@ class SignalRequestMiddleware:
self.get_response = get_response self.get_response = get_response
def __call__(self, request): def __call__(self, request):
setattr(_threadlocal, "request", request) _threadlocal.request = request
return self.get_response(request) return self.get_response(request)

View File

@ -1,4 +1,3 @@
# -*- coding: utf-8 -*-
from __future__ import unicode_literals from __future__ import unicode_literals
import django.contrib.auth.models import django.contrib.auth.models
@ -574,7 +573,7 @@ class Migration(migrations.Migration):
managers=[("objects", core.models.RealGroupManager())], managers=[("objects", core.models.RealGroupManager())],
), ),
migrations.AlterUniqueTogether( migrations.AlterUniqueTogether(
name="page", unique_together=set([("name", "parent")]) name="page", unique_together={("name", "parent")}
), ),
migrations.AddField( migrations.AddField(
model_name="user", model_name="user",

View File

@ -1,4 +1,3 @@
# -*- coding: utf-8 -*-
from __future__ import unicode_literals from __future__ import unicode_literals
from django.db import migrations, models from django.db import migrations, models

View File

@ -1,4 +1,3 @@
# -*- coding: utf-8 -*-
from __future__ import unicode_literals from __future__ import unicode_literals
import django.core.validators import django.core.validators

View File

@ -1,4 +1,3 @@
# -*- coding: utf-8 -*-
from __future__ import unicode_literals from __future__ import unicode_literals
from django.conf import settings from django.conf import settings

View File

@ -1,4 +1,3 @@
# -*- coding: utf-8 -*-
from __future__ import unicode_literals from __future__ import unicode_literals
import django.db.models.deletion import django.db.models.deletion

View File

@ -1,4 +1,3 @@
# -*- coding: utf-8 -*-
from __future__ import unicode_literals from __future__ import unicode_literals
from django.db import migrations, models from django.db import migrations, models

View File

@ -1,4 +1,3 @@
# -*- coding: utf-8 -*-
from __future__ import unicode_literals from __future__ import unicode_literals
from django.db import migrations, models from django.db import migrations, models

View File

@ -1,4 +1,3 @@
# -*- coding: utf-8 -*-
from __future__ import unicode_literals from __future__ import unicode_literals
import django.db.models.deletion import django.db.models.deletion

View File

@ -1,4 +1,3 @@
# -*- coding: utf-8 -*-
from __future__ import unicode_literals from __future__ import unicode_literals
from django.db import migrations, models from django.db import migrations, models

View File

@ -1,4 +1,3 @@
# -*- coding: utf-8 -*-
from __future__ import unicode_literals from __future__ import unicode_literals
import django.utils.timezone import django.utils.timezone

View File

@ -1,4 +1,3 @@
# -*- coding: utf-8 -*-
from __future__ import unicode_literals from __future__ import unicode_literals
import django.db.models.deletion import django.db.models.deletion

View File

@ -1,4 +1,3 @@
# -*- coding: utf-8 -*-
from __future__ import unicode_literals from __future__ import unicode_literals
from django.db import migrations, models from django.db import migrations, models

View File

@ -1,4 +1,3 @@
# -*- coding: utf-8 -*-
from __future__ import unicode_literals from __future__ import unicode_literals
from django.db import migrations, models from django.db import migrations, models

View File

@ -1,4 +1,3 @@
# -*- coding: utf-8 -*-
from __future__ import unicode_literals from __future__ import unicode_literals
import django.db.models.deletion import django.db.models.deletion

View File

@ -1,4 +1,3 @@
# -*- coding: utf-8 -*-
from __future__ import unicode_literals from __future__ import unicode_literals
import django.db.models.deletion import django.db.models.deletion

View File

@ -1,4 +1,3 @@
# -*- coding: utf-8 -*-
from __future__ import unicode_literals from __future__ import unicode_literals
from django.db import migrations, models from django.db import migrations, models

View File

@ -1,4 +1,3 @@
# -*- coding: utf-8 -*-
from __future__ import unicode_literals from __future__ import unicode_literals
from django.db import migrations, models from django.db import migrations, models

View File

@ -1,4 +1,3 @@
# -*- coding: utf-8 -*-
from __future__ import unicode_literals from __future__ import unicode_literals
from django.db import migrations, models from django.db import migrations, models

View File

@ -1,4 +1,3 @@
# -*- coding: utf-8 -*-
from __future__ import unicode_literals from __future__ import unicode_literals
import django.core.validators import django.core.validators

View File

@ -1,4 +1,3 @@
# -*- coding: utf-8 -*-
from __future__ import unicode_literals from __future__ import unicode_literals
from django.db import migrations, models from django.db import migrations, models

View File

@ -1,4 +1,3 @@
# -*- coding: utf-8 -*-
from __future__ import unicode_literals from __future__ import unicode_literals
from django.db import migrations, models from django.db import migrations, models

View File

@ -1,4 +1,3 @@
# -*- coding: utf-8 -*-
from __future__ import unicode_literals from __future__ import unicode_literals
import django.db.models.deletion import django.db.models.deletion

View File

@ -1,4 +1,3 @@
# -*- coding: utf-8 -*-
from __future__ import unicode_literals from __future__ import unicode_literals
from django.db import migrations, models from django.db import migrations, models

View File

@ -1,4 +1,3 @@
# -*- coding: utf-8 -*-
from __future__ import unicode_literals from __future__ import unicode_literals
import django.core.validators import django.core.validators

View File

@ -1,4 +1,3 @@
# -*- coding: utf-8 -*-
from __future__ import unicode_literals from __future__ import unicode_literals
from django.db import migrations, models from django.db import migrations, models

View File

@ -1,4 +1,3 @@
# -*- coding: utf-8 -*-
from __future__ import unicode_literals from __future__ import unicode_literals
import django.db.models.deletion import django.db.models.deletion

Some files were not shown because too many files have changed in this diff Show More