diff --git a/accounting/__init__.py b/accounting/__init__.py index 0aa913c4..a098e7ba 100644 --- a/accounting/__init__.py +++ b/accounting/__init__.py @@ -1,4 +1,3 @@ -# -*- coding:utf-8 -* # # Copyright 2023 © AE UTBM # ae@utbm.fr / ae.info@utbm.fr diff --git a/accounting/admin.py b/accounting/admin.py index 95216e59..f0a3784e 100644 --- a/accounting/admin.py +++ b/accounting/admin.py @@ -1,4 +1,3 @@ -# -*- coding:utf-8 -* # # Copyright 2023 © AE UTBM # ae@utbm.fr / ae.info@utbm.fr diff --git a/accounting/migrations/0001_initial.py b/accounting/migrations/0001_initial.py index b5112cdd..2f22da8d 100644 --- a/accounting/migrations/0001_initial.py +++ b/accounting/migrations/0001_initial.py @@ -1,4 +1,3 @@ -# -*- coding: utf-8 -*- from __future__ import unicode_literals import django.core.validators diff --git a/accounting/migrations/0002_auto_20160824_2152.py b/accounting/migrations/0002_auto_20160824_2152.py index d331dd5c..adfc0225 100644 --- a/accounting/migrations/0002_auto_20160824_2152.py +++ b/accounting/migrations/0002_auto_20160824_2152.py @@ -1,4 +1,3 @@ -# -*- coding: utf-8 -*- from __future__ import unicode_literals import django.db.models.deletion @@ -101,6 +100,6 @@ class Migration(migrations.Migration): ), ), migrations.AlterUniqueTogether( - name="operation", unique_together=set([("number", "journal")]) + name="operation", unique_together={("number", "journal")} ), ] diff --git a/accounting/migrations/0003_auto_20160824_2203.py b/accounting/migrations/0003_auto_20160824_2203.py index cf53223f..7fa3910a 100644 --- a/accounting/migrations/0003_auto_20160824_2203.py +++ b/accounting/migrations/0003_auto_20160824_2203.py @@ -1,4 +1,3 @@ -# -*- coding: utf-8 -*- from __future__ import unicode_literals import phonenumber_field.modelfields diff --git a/accounting/migrations/0004_auto_20161005_1505.py b/accounting/migrations/0004_auto_20161005_1505.py index 6e122f7d..fe8fd3c4 100644 --- a/accounting/migrations/0004_auto_20161005_1505.py +++ b/accounting/migrations/0004_auto_20161005_1505.py @@ -1,4 +1,3 @@ -# -*- coding: utf-8 -*- from __future__ import unicode_literals import django.db.models.deletion @@ -46,6 +45,6 @@ class Migration(migrations.Migration): ), ), migrations.AlterUniqueTogether( - name="label", unique_together=set([("name", "club_account")]) + name="label", unique_together={("name", "club_account")} ), ] diff --git a/accounting/migrations/0005_auto_20170324_0917.py b/accounting/migrations/0005_auto_20170324_0917.py index 76bcbed6..3f640fd0 100644 --- a/accounting/migrations/0005_auto_20170324_0917.py +++ b/accounting/migrations/0005_auto_20170324_0917.py @@ -1,4 +1,3 @@ -# -*- coding: utf-8 -*- from __future__ import unicode_literals from django.db import migrations, models diff --git a/accounting/models.py b/accounting/models.py index 55bdda46..254a41ba 100644 --- a/accounting/models.py +++ b/accounting/models.py @@ -1,4 +1,3 @@ -# -*- coding:utf-8 -* # # Copyright 2023 © AE UTBM # ae@utbm.fr / ae.info@utbm.fr @@ -37,11 +36,11 @@ class CurrencyField(models.DecimalField): def __init__(self, *args, **kwargs): kwargs["max_digits"] = 12 kwargs["decimal_places"] = 2 - super(CurrencyField, self).__init__(*args, **kwargs) + super().__init__(*args, **kwargs) def to_python(self, value): try: - return super(CurrencyField, self).to_python(value).quantize(Decimal("0.01")) + return super().to_python(value).quantize(Decimal("0.01")) except AttributeError: return None @@ -62,6 +61,15 @@ class Company(models.Model): class Meta: 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): """ Method to see if that object can be edited by the given user @@ -88,15 +96,6 @@ class Company(models.Model): return True 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): name = models.CharField(_("name"), max_length=30) @@ -113,6 +112,12 @@ class BankAccount(models.Model): verbose_name = _("Bank account") 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): """ Method to see if that object can be edited by the given user @@ -126,12 +131,6 @@ class BankAccount(models.Model): return True 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): name = models.CharField(_("name"), max_length=30) @@ -152,6 +151,12 @@ class ClubAccount(models.Model): verbose_name = _("Club account") 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): """ 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): 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): return _("%(club_account)s on %(bank_account)s") % { "club_account": self.name, @@ -225,6 +224,12 @@ class GeneralJournal(models.Model): verbose_name = _("General journal") 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): """ 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): 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): self.amount = 0 self.effective_amount = 0 @@ -357,6 +356,18 @@ class Operation(models.Model): unique_together = ("number", "journal") 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): if attr == "target": return self.get_target() @@ -364,7 +375,7 @@ class Operation(models.Model): return object.__getattribute__(self, attr) def clean(self): - super(Operation, self).clean() + super().clean() if self.date is None: raise ValidationError(_("The date must be set.")) elif self.date < self.journal.start_date: @@ -410,12 +421,6 @@ class Operation(models.Model): tar = Company.objects.filter(id=self.target_id).first() 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): """ Method to see if that object can be edited by the given user @@ -444,17 +449,6 @@ class Operation(models.Model): return True 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): """ @@ -487,6 +481,12 @@ class AccountingType(models.Model): verbose_name = _("accounting type") 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): """ Method to see if that object can be edited by the given user @@ -497,12 +497,6 @@ class AccountingType(models.Model): return True 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): """ @@ -521,6 +515,15 @@ class SimplifiedAccountingType(models.Model): verbose_name = _("simplified type") 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 def movement_type(self): return self.accounting_type.movement_type @@ -528,18 +531,6 @@ class SimplifiedAccountingType(models.Model): def get_movement_type_display(self): 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): """Label allow a club to sort its operations""" diff --git a/accounting/tests.py b/accounting/tests.py index 0ea7a29e..78a8c0ef 100644 --- a/accounting/tests.py +++ b/accounting/tests.py @@ -1,4 +1,3 @@ -# -*- coding:utf-8 -* # # Copyright 2023 © AE UTBM # ae@utbm.fr / ae.info@utbm.fr diff --git a/accounting/urls.py b/accounting/urls.py index 7363cd48..029cd4cc 100644 --- a/accounting/urls.py +++ b/accounting/urls.py @@ -1,4 +1,3 @@ -# -*- coding:utf-8 -* # # Copyright 2023 © AE UTBM # ae@utbm.fr / ae.info@utbm.fr diff --git a/accounting/views.py b/accounting/views.py index f9618beb..691bbbdc 100644 --- a/accounting/views.py +++ b/accounting/views.py @@ -1,4 +1,3 @@ -# -*- coding:utf-8 -* # # Copyright 2023 © AE UTBM # ae@utbm.fr / ae.info@utbm.fr @@ -210,7 +209,7 @@ class ClubAccountCreateView(CanCreateMixin, CreateView): template_name = "core/create.jinja" def get_initial(self): - ret = super(ClubAccountCreateView, self).get_initial() + ret = super().get_initial() if "parent" in self.request.GET.keys(): obj = BankAccount.objects.filter(id=int(self.request.GET["parent"])).first() if obj is not None: @@ -296,7 +295,7 @@ class JournalCreateView(CanCreateMixin, CreateView): template_name = "core/create.jinja" def get_initial(self): - ret = super(JournalCreateView, self).get_initial() + ret = super().get_initial() if "parent" in self.request.GET.keys(): obj = ClubAccount.objects.filter(id=int(self.request.GET["parent"])).first() if obj is not None: @@ -339,7 +338,7 @@ class JournalDeleteView(CanEditPropMixin, DeleteView): def dispatch(self, request, *args, **kwargs): self.object = self.get_object() if self.object.operations.count() == 0: - return super(JournalDeleteView, self).dispatch(request, *args, **kwargs) + return super().dispatch(request, *args, **kwargs) else: raise PermissionDenied @@ -387,7 +386,7 @@ class OperationForm(forms.ModelForm): def __init__(self, *args, **kwargs): club_account = kwargs.pop("club_account", None) - super(OperationForm, self).__init__(*args, **kwargs) + super().__init__(*args, **kwargs) if club_account: self.fields["label"].queryset = club_account.labels.order_by("name").all() if self.instance.target_type == "USER": @@ -400,7 +399,7 @@ class OperationForm(forms.ModelForm): self.fields["company"].initial = self.instance.target_id def clean(self): - self.cleaned_data = super(OperationForm, self).clean() + self.cleaned_data = super().clean() if "target_type" in self.cleaned_data.keys(): if ( self.cleaned_data.get("user") is None @@ -430,7 +429,7 @@ class OperationForm(forms.ModelForm): return self.cleaned_data def save(self): - ret = super(OperationForm, self).save() + ret = super().save() if ( self.instance.target_type == "ACCOUNT" 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()) def get_initial(self): - ret = super(OperationCreateView, self).get_initial() + ret = super().get_initial() if self.journal is not None: ret["journal"] = self.journal.id return ret def get_context_data(self, **kwargs): """Add journal to the context""" - kwargs = super(OperationCreateView, self).get_context_data(**kwargs) + kwargs = super().get_context_data(**kwargs) if self.journal: kwargs["object"] = self.journal return kwargs @@ -507,7 +506,7 @@ class OperationEditView(CanEditMixin, UpdateView): def get_context_data(self, **kwargs): """Add journal to the context""" - kwargs = super(OperationEditView, self).get_context_data(**kwargs) + kwargs = super().get_context_data(**kwargs) kwargs["object"] = self.object.journal return kwargs @@ -683,16 +682,16 @@ class JournalNatureStatementView(JournalTabsMixin, CanViewMixin, DetailView): for sat in [None] + list( SimplifiedAccountingType.objects.order_by("label").all() ): - sum = queryset.filter( + amount = queryset.filter( accounting_type__movement_type=movement_type, simpleaccounting_type=sat ).aggregate(amount_sum=Sum("amount"))["amount_sum"] if sat: sat = sat.label else: sat = "" - if sum: - total_sum += sum - statement[sat] = sum + if amount: + total_sum += amount + statement[sat] = amount ret[movement_type] = statement ret[movement_type + "_sum"] = total_sum return ret @@ -728,7 +727,7 @@ class JournalNatureStatementView(JournalTabsMixin, CanViewMixin, DetailView): def get_context_data(self, **kwargs): """Add infos to the context""" - kwargs = super(JournalNatureStatementView, self).get_context_data(**kwargs) + kwargs = super().get_context_data(**kwargs) kwargs["statement"] = self.big_statement() return kwargs @@ -767,7 +766,7 @@ class JournalPersonStatementView(JournalTabsMixin, CanViewMixin, DetailView): def get_context_data(self, **kwargs): """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["debit_statement"] = self.statement("DEBIT") kwargs["total_credit"] = self.total("CREDIT") @@ -797,7 +796,7 @@ class JournalAccountingStatementView(JournalTabsMixin, CanViewMixin, DetailView) def get_context_data(self, **kwargs): """Add journal to the context""" - kwargs = super(JournalAccountingStatementView, self).get_context_data(**kwargs) + kwargs = super().get_context_data(**kwargs) kwargs["statement"] = self.statement() return kwargs @@ -852,7 +851,7 @@ class LabelCreateView( template_name = "core/create.jinja" def get_initial(self): - ret = super(LabelCreateView, self).get_initial() + ret = super().get_initial() if "parent" in self.request.GET.keys(): obj = ClubAccount.objects.filter(id=int(self.request.GET["parent"])).first() if obj is not None: @@ -897,19 +896,19 @@ class RefoundAccountView(FormView): raise PermissionDenied 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): return res def post(self, request, *arg, **kwargs): self.operator = 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): self.customer = form.cleaned_data["user"] self.create_selling() - return super(RefoundAccountView, self).form_valid(form) + return super().form_valid(form) def get_success_url(self): return reverse("accounting:refound_account") diff --git a/api/__init__.py b/api/__init__.py index 0aa913c4..a098e7ba 100644 --- a/api/__init__.py +++ b/api/__init__.py @@ -1,4 +1,3 @@ -# -*- coding:utf-8 -* # # Copyright 2023 © AE UTBM # ae@utbm.fr / ae.info@utbm.fr diff --git a/api/admin.py b/api/admin.py index 5531f2a2..1a02ff3a 100644 --- a/api/admin.py +++ b/api/admin.py @@ -1,4 +1,3 @@ -# -*- coding:utf-8 -* # # Copyright 2023 © AE UTBM # ae@utbm.fr / ae.info@utbm.fr diff --git a/api/models.py b/api/models.py index 084dfa73..c6372d7f 100644 --- a/api/models.py +++ b/api/models.py @@ -1,4 +1,3 @@ -# -*- coding:utf-8 -* # # Copyright 2023 © AE UTBM # ae@utbm.fr / ae.info@utbm.fr diff --git a/api/tests.py b/api/tests.py index d888e761..48d8f1f6 100644 --- a/api/tests.py +++ b/api/tests.py @@ -1,4 +1,3 @@ -# -*- coding:utf-8 -* # # Copyright 2023 © AE UTBM # ae@utbm.fr / ae.info@utbm.fr diff --git a/api/urls.py b/api/urls.py index 4dde736c..15bc6839 100644 --- a/api/urls.py +++ b/api/urls.py @@ -1,4 +1,3 @@ -# -*- coding:utf-8 -* # # Copyright 2023 © AE UTBM # ae@utbm.fr / ae.info@utbm.fr diff --git a/api/views/__init__.py b/api/views/__init__.py index b0157985..d5ca6289 100644 --- a/api/views/__init__.py +++ b/api/views/__init__.py @@ -1,4 +1,3 @@ -# -*- coding:utf-8 -* # # Copyright 2023 © AE UTBM # ae@utbm.fr / ae.info@utbm.fr @@ -50,7 +49,7 @@ class ManageModelMixin: class RightModelViewSet(ManageModelMixin, viewsets.ModelViewSet): def dispatch(self, request, *arg, **kwargs): - res = super(RightModelViewSet, self).dispatch(request, *arg, **kwargs) + res = super().dispatch(request, *arg, **kwargs) obj = self.queryset user = self.request.user try: diff --git a/api/views/api.py b/api/views/api.py index 4329a98b..6e3a056d 100644 --- a/api/views/api.py +++ b/api/views/api.py @@ -1,4 +1,3 @@ -# -*- coding:utf-8 -* # # Copyright 2023 © AE UTBM # ae@utbm.fr / ae.info@utbm.fr diff --git a/api/views/club.py b/api/views/club.py index a08d6c4f..2333fffb 100644 --- a/api/views/club.py +++ b/api/views/club.py @@ -1,4 +1,3 @@ -# -*- coding:utf-8 -* # # Copyright 2023 © AE UTBM # ae@utbm.fr / ae.info@utbm.fr diff --git a/api/views/counter.py b/api/views/counter.py index 2e633cae..a9fd64ce 100644 --- a/api/views/counter.py +++ b/api/views/counter.py @@ -1,4 +1,3 @@ -# -*- coding:utf-8 -* # # Copyright 2023 © AE UTBM # ae@utbm.fr / ae.info@utbm.fr diff --git a/api/views/group.py b/api/views/group.py index a6aa7e2b..c9183ed0 100644 --- a/api/views/group.py +++ b/api/views/group.py @@ -1,4 +1,3 @@ -# -*- coding:utf-8 -* # # Copyright 2023 © AE UTBM # ae@utbm.fr / ae.info@utbm.fr diff --git a/api/views/launderette.py b/api/views/launderette.py index a1225274..eae35a19 100644 --- a/api/views/launderette.py +++ b/api/views/launderette.py @@ -1,4 +1,3 @@ -# -*- coding:utf-8 -* # # Copyright 2023 © AE UTBM # ae@utbm.fr / ae.info@utbm.fr diff --git a/api/views/user.py b/api/views/user.py index a9ad19a6..d5aecd15 100644 --- a/api/views/user.py +++ b/api/views/user.py @@ -1,4 +1,3 @@ -# -*- coding:utf-8 -* # # Copyright 2023 © AE UTBM # ae@utbm.fr / ae.info@utbm.fr diff --git a/club/__init__.py b/club/__init__.py index 0aa913c4..a098e7ba 100644 --- a/club/__init__.py +++ b/club/__init__.py @@ -1,4 +1,3 @@ -# -*- coding:utf-8 -* # # Copyright 2023 © AE UTBM # ae@utbm.fr / ae.info@utbm.fr diff --git a/club/admin.py b/club/admin.py index c9b547b5..3cdaf0ff 100644 --- a/club/admin.py +++ b/club/admin.py @@ -1,4 +1,3 @@ -# -*- coding:utf-8 -* # # Copyright 2023 © AE UTBM # ae@utbm.fr / ae.info@utbm.fr diff --git a/club/forms.py b/club/forms.py index ca6cb324..ad3273c6 100644 --- a/club/forms.py +++ b/club/forms.py @@ -1,4 +1,3 @@ -# -*- coding:utf-8 -* # # Copyright 2016,2017 # - Skia @@ -40,7 +39,7 @@ class ClubEditForm(forms.ModelForm): fields = ["address", "logo", "short_description"] def __init__(self, *args, **kwargs): - super(ClubEditForm, self).__init__(*args, **kwargs) + super().__init__(*args, **kwargs) 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): - super(MailingForm, self).__init__(*args, **kwargs) + super().__init__(*args, **kwargs) self.fields["action"] = forms.TypedChoiceField( choices=( @@ -116,7 +115,7 @@ class MailingForm(forms.Form): """ Convert given users into real users and check their validity """ - cleaned_data = super(MailingForm, self).clean() + cleaned_data = super().clean() users = [] for user in cleaned_data["subscription_users"]: user = User.objects.filter(id=user).first() @@ -133,7 +132,7 @@ class MailingForm(forms.Form): return users def clean(self): - cleaned_data = super(MailingForm, self).clean() + cleaned_data = super().clean() if not "action" in cleaned_data: # If there is no action provided, we can stop here @@ -164,7 +163,7 @@ class SellingsForm(forms.Form): ) def __init__(self, club, *args, **kwargs): - super(SellingsForm, self).__init__(*args, **kwargs) + super().__init__(*args, **kwargs) self.fields["products"] = forms.ModelMultipleChoiceField( club.products.order_by("name").filter(archived=False).all(), label=_("Products"), @@ -201,7 +200,7 @@ class ClubMemberForm(forms.Form): self.club.members.filter(end_date=None).order_by("-role").all() ) 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 # 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 Also check that the user is valid and has a valid subscription """ - cleaned_data = super(ClubMemberForm, self).clean() + cleaned_data = super().clean() users = [] for user_id in cleaned_data["users"]: user = User.objects.filter(id=user_id).first() @@ -264,7 +263,7 @@ class ClubMemberForm(forms.Form): """ 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"]: # Drop start_date if allowed to edition but not specified diff --git a/club/migrations/0001_initial.py b/club/migrations/0001_initial.py index 4a26270e..706df0c8 100644 --- a/club/migrations/0001_initial.py +++ b/club/migrations/0001_initial.py @@ -1,4 +1,3 @@ -# -*- coding: utf-8 -*- from __future__ import unicode_literals import django.core.validators diff --git a/club/migrations/0002_auto_20160824_2152.py b/club/migrations/0002_auto_20160824_2152.py index ffc57443..5ecdfb57 100644 --- a/club/migrations/0002_auto_20160824_2152.py +++ b/club/migrations/0002_auto_20160824_2152.py @@ -1,4 +1,3 @@ -# -*- coding: utf-8 -*- from __future__ import unicode_literals import django.db.models.deletion diff --git a/club/migrations/0003_auto_20160902_2042.py b/club/migrations/0003_auto_20160902_2042.py index 7a3d05cd..b9c11983 100644 --- a/club/migrations/0003_auto_20160902_2042.py +++ b/club/migrations/0003_auto_20160902_2042.py @@ -1,4 +1,3 @@ -# -*- coding: utf-8 -*- from __future__ import unicode_literals from django.db import migrations, models diff --git a/club/migrations/0004_auto_20160915_1057.py b/club/migrations/0004_auto_20160915_1057.py index 8e0dc244..435e6d23 100644 --- a/club/migrations/0004_auto_20160915_1057.py +++ b/club/migrations/0004_auto_20160915_1057.py @@ -1,4 +1,3 @@ -# -*- coding: utf-8 -*- from __future__ import unicode_literals import django.db.models.deletion diff --git a/club/migrations/0005_auto_20161120_1149.py b/club/migrations/0005_auto_20161120_1149.py index b9eda617..31cddb31 100644 --- a/club/migrations/0005_auto_20161120_1149.py +++ b/club/migrations/0005_auto_20161120_1149.py @@ -1,4 +1,3 @@ -# -*- coding: utf-8 -*- from __future__ import unicode_literals import django.db.models.deletion diff --git a/club/migrations/0006_auto_20161229_0040.py b/club/migrations/0006_auto_20161229_0040.py index fec86868..117ef947 100644 --- a/club/migrations/0006_auto_20161229_0040.py +++ b/club/migrations/0006_auto_20161229_0040.py @@ -1,4 +1,3 @@ -# -*- coding: utf-8 -*- from __future__ import unicode_literals import django.utils.timezone diff --git a/club/migrations/0007_auto_20170324_0917.py b/club/migrations/0007_auto_20170324_0917.py index e356bac2..f9005d77 100644 --- a/club/migrations/0007_auto_20170324_0917.py +++ b/club/migrations/0007_auto_20170324_0917.py @@ -1,4 +1,3 @@ -# -*- coding: utf-8 -*- from __future__ import unicode_literals from django.db import migrations diff --git a/club/migrations/0008_auto_20170515_2214.py b/club/migrations/0008_auto_20170515_2214.py index 52bb1074..a9f01431 100644 --- a/club/migrations/0008_auto_20170515_2214.py +++ b/club/migrations/0008_auto_20170515_2214.py @@ -1,4 +1,3 @@ -# -*- coding: utf-8 -*- from __future__ import unicode_literals from django.db import migrations, models diff --git a/club/migrations/0009_auto_20170822_2232.py b/club/migrations/0009_auto_20170822_2232.py index 4e679d09..8b98dbef 100644 --- a/club/migrations/0009_auto_20170822_2232.py +++ b/club/migrations/0009_auto_20170822_2232.py @@ -1,4 +1,3 @@ -# -*- coding: utf-8 -*- from __future__ import unicode_literals import re @@ -110,6 +109,6 @@ class Migration(migrations.Migration): ), migrations.AlterUniqueTogether( name="mailingsubscription", - unique_together=set([("user", "email", "mailing")]), + unique_together={("user", "email", "mailing")}, ), ] diff --git a/club/migrations/0010_auto_20170912_2028.py b/club/migrations/0010_auto_20170912_2028.py index 0dbf796a..d6e28063 100644 --- a/club/migrations/0010_auto_20170912_2028.py +++ b/club/migrations/0010_auto_20170912_2028.py @@ -1,4 +1,3 @@ -# -*- coding: utf-8 -*- from __future__ import unicode_literals import django.db.models.deletion diff --git a/club/migrations/0010_club_logo.py b/club/migrations/0010_club_logo.py index 87cc4bba..c4ca9c46 100644 --- a/club/migrations/0010_club_logo.py +++ b/club/migrations/0010_club_logo.py @@ -1,4 +1,3 @@ -# -*- coding: utf-8 -*- from __future__ import unicode_literals from django.db import migrations, models diff --git a/club/migrations/0011_auto_20180426_2013.py b/club/migrations/0011_auto_20180426_2013.py index b1b1d362..c10fe7b7 100644 --- a/club/migrations/0011_auto_20180426_2013.py +++ b/club/migrations/0011_auto_20180426_2013.py @@ -1,4 +1,3 @@ -# -*- coding: utf-8 -*- from __future__ import unicode_literals import django.db.models.deletion @@ -16,7 +15,7 @@ class Migration(migrations.Migration): name="owner_group", field=models.ForeignKey( 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", to="core.Group", ), diff --git a/club/models.py b/club/models.py index 10f1cd59..e315f1d2 100644 --- a/club/models.py +++ b/club/models.py @@ -1,4 +1,3 @@ -# -*- coding:utf-8 -* # # Copyright 2016,2017 # - Skia @@ -41,6 +40,11 @@ from core.models import Group, MetaGroup, Notification, Page, RealGroup, SithFil # 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): """ 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) - # This function prevents generating migration upon settings change - def get_default_owner_group(): - return settings.SITH_GROUP_ROOT_ID - owner_group = models.ForeignKey( Group, related_name="owned_club", @@ -106,6 +106,34 @@ class Club(models.Model): class Meta: 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 def president(self): return self.members.filter( @@ -184,28 +212,6 @@ class Club(models.Model): self.page.parent = self.parent.page 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): # Invalidate the cache of this club and of its memberships 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}") 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): return self.name @@ -374,14 +374,21 @@ class Membership(models.Model): def __str__(self): return ( - self.club.name - + " - " - + self.user.username - + " - " - + str(settings.SITH_CLUB_ROLES[self.role]) - + str(" - " + str(_("past member")) if self.end_date is not None else "") + f"{self.club.name} - {self.user.username} " + f"- {settings.SITH_CLUB_ROLES[self.role]} " + f"- {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): """ 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 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): super().delete(*args, **kwargs) cache.delete(f"membership_{self.club_id}_{self.user_id}") @@ -452,6 +449,26 @@ class Mailing(models.Model): 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): if Mailing.objects.filter(email=self.email).exists(): raise ValidationError(_("This mailing list already exists.")) @@ -459,7 +476,7 @@ class Mailing(models.Model): self.is_moderated = True else: self.moderator = None - super(Mailing, self).clean() + super().clean() @property def email_full(self): @@ -481,7 +498,7 @@ class Mailing(models.Model): def delete(self, *args, **kwargs): self.subscriptions.all().delete() - super(Mailing, self).delete() + super().delete() def fetch_format(self): resp = self.email + ": " @@ -489,26 +506,6 @@ class Mailing(models.Model): resp += sub.fetch_format() 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): """ @@ -536,6 +533,9 @@ class MailingSubscription(models.Model): class Meta: unique_together = (("user", "email", "mailing"),) + def __str__(self): + return "(%s) - %s : %s" % (self.mailing, self.get_username, self.email) + def clean(self): if not self.user and not self.email: raise ValidationError(_("At least user or email is required")) @@ -550,7 +550,7 @@ class MailingSubscription(models.Model): ) except ObjectDoesNotExist: pass - super(MailingSubscription, self).clean() + super().clean() def is_owned_by(self, user): if user.is_anonymous: @@ -578,6 +578,3 @@ class MailingSubscription(models.Model): def fetch_format(self): return self.get_email + " " - - def __str__(self): - return "(%s) - %s : %s" % (self.mailing, self.get_username, self.email) diff --git a/club/tests.py b/club/tests.py index 78fb8665..b893cb99 100644 --- a/club/tests.py +++ b/club/tests.py @@ -1,4 +1,3 @@ -# -*- coding:utf-8 -* # # Copyright 2023 © AE UTBM # ae@utbm.fr / ae.info@utbm.fr diff --git a/club/urls.py b/club/urls.py index d33a5167..a57e36e4 100644 --- a/club/urls.py +++ b/club/urls.py @@ -1,4 +1,3 @@ -# -*- coding:utf-8 -* # # Copyright 2016,2017 # - Skia diff --git a/club/views.py b/club/views.py index 1d738b8e..2bc743b9 100644 --- a/club/views.py +++ b/club/views.py @@ -1,4 +1,3 @@ -# -*- coding:utf-8 -* # # Copyright 2016,2017 # - Skia @@ -195,7 +194,7 @@ class ClubView(ClubTabsMixin, DetailView): current_tab = "infos" 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(): kwargs["page_revision"] = self.object.page.revisions.last().content return kwargs @@ -209,10 +208,10 @@ class ClubRevView(ClubView): def dispatch(self, request, *args, **kwargs): obj = self.get_object() 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): - kwargs = super(ClubRevView, self).get_context_data(**kwargs) + kwargs = super().get_context_data(**kwargs) kwargs["page_revision"] = self.revision.content return kwargs @@ -225,7 +224,7 @@ class ClubPageEditView(ClubTabsMixin, PageEditViewBase): self.club = get_object_or_404(Club, pk=kwargs["club_id"]) if not self.club.page: raise Http404 - return super(ClubPageEditView, self).dispatch(request, *args, **kwargs) + return super().dispatch(request, *args, **kwargs) def get_object(self): self.page = self.club.page @@ -269,14 +268,14 @@ class ClubMembersView(ClubTabsMixin, CanViewMixin, DetailFormView): current_tab = "members" def get_form_kwargs(self): - kwargs = super(ClubMembersView, self).get_form_kwargs() + kwargs = super().get_form_kwargs() kwargs["request_user"] = self.request.user kwargs["club"] = self.get_object() kwargs["club_members"] = self.members return 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 return kwargs @@ -284,7 +283,7 @@ class ClubMembersView(ClubTabsMixin, CanViewMixin, DetailFormView): """ Check user rights """ - resp = super(ClubMembersView, self).form_valid(form) + resp = super().form_valid(form) data = form.clean() users = data.pop("users", []) @@ -299,7 +298,7 @@ class ClubMembersView(ClubTabsMixin, CanViewMixin, DetailFormView): def dispatch(self, request, *args, **kwargs): 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): return reverse_lazy( @@ -333,12 +332,12 @@ class ClubSellingView(ClubTabsMixin, CanEditMixin, DetailFormView): def dispatch(self, request, *args, **kwargs): try: self.asked_page = int(request.GET.get("page", 1)) - except ValueError: - raise Http404 - return super(ClubSellingView, self).dispatch(request, *args, **kwargs) + except ValueError as e: + raise Http404 from e + return super().dispatch(request, *args, **kwargs) def get_form_kwargs(self): - kwargs = super(ClubSellingView, self).get_form_kwargs() + kwargs = super().get_form_kwargs() kwargs["club"] = self.object return kwargs @@ -346,7 +345,7 @@ class ClubSellingView(ClubTabsMixin, CanEditMixin, DetailFormView): return self.get(request, *args, **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) kwargs["result"] = qs[:0] @@ -390,8 +389,8 @@ class ClubSellingView(ClubTabsMixin, CanEditMixin, DetailFormView): kwargs["paginator"] = Paginator(kwargs["result"], self.paginate_by) try: kwargs["paginated_result"] = kwargs["paginator"].page(self.asked_page) - except InvalidPage: - raise Http404 + except InvalidPage as e: + raise Http404 from e return kwargs @@ -558,7 +557,7 @@ class ClubStatView(TemplateView): template_name = "club/stats.jinja" 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() return kwargs @@ -575,7 +574,7 @@ class ClubMailingView(ClubTabsMixin, CanEditMixin, DetailFormView): current_tab = "mailing" 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["user_id"] = self.request.user.id kwargs["mailings"] = self.mailings @@ -583,10 +582,10 @@ class ClubMailingView(ClubTabsMixin, CanEditMixin, DetailFormView): def dispatch(self, request, *args, **kwargs): 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): - kwargs = super(ClubMailingView, self).get_context_data(**kwargs) + kwargs = super().get_context_data(**kwargs) kwargs["club"] = self.get_object() kwargs["user"] = self.request.user kwargs["mailings"] = self.mailings @@ -670,7 +669,7 @@ class ClubMailingView(ClubTabsMixin, CanEditMixin, DetailFormView): sub.delete() def form_valid(self, form): - resp = super(ClubMailingView, self).form_valid(form) + resp = super().form_valid(form) cleaned_data = form.clean() error = None @@ -702,7 +701,7 @@ class MailingDeleteView(CanEditMixin, DeleteView): def dispatch(self, request, *args, **kwargs): 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): if self.redirect_page: @@ -718,9 +717,7 @@ class MailingSubscriptionDeleteView(CanEditMixin, DeleteView): def dispatch(self, request, *args, **kwargs): self.club_id = self.get_object().mailing.club.id - return super(MailingSubscriptionDeleteView, self).dispatch( - request, *args, **kwargs - ) + return super().dispatch(request, *args, **kwargs) def get_success_url(self, **kwargs): 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"]) if not request.user.can_edit(self.mailing): raise PermissionDenied - return super(MailingAutoGenerationView, self).dispatch(request, *args, **kwargs) + return super().dispatch(request, *args, **kwargs) def get(self, request, *args, **kwargs): club = self.mailing.club @@ -751,7 +748,7 @@ class PosterListView(ClubTabsMixin, PosterListBaseView, CanViewMixin): return self.club def get_context_data(self, **kwargs): - kwargs = super(PosterListView, self).get_context_data(**kwargs) + kwargs = super().get_context_data(**kwargs) kwargs["app"] = "club" kwargs["club"] = self.club return kwargs @@ -763,7 +760,7 @@ class PosterCreateView(PosterCreateBaseView, CanCreateMixin): pk_url_kwarg = "club_id" def get_object(self): - obj = super(PosterCreateView, self).get_object() + obj = super().get_object() if not obj: return self.club return obj @@ -779,7 +776,7 @@ class PosterEditView(ClubTabsMixin, PosterEditBaseView, CanEditMixin): return reverse_lazy("club:poster_list", kwargs={"club_id": self.club.id}) def get_context_data(self, **kwargs): - kwargs = super(PosterEditView, self).get_context_data(**kwargs) + kwargs = super().get_context_data(**kwargs) kwargs["app"] = "club" return kwargs diff --git a/com/__init__.py b/com/__init__.py index 0aa913c4..a098e7ba 100644 --- a/com/__init__.py +++ b/com/__init__.py @@ -1,4 +1,3 @@ -# -*- coding:utf-8 -* # # Copyright 2023 © AE UTBM # ae@utbm.fr / ae.info@utbm.fr diff --git a/com/admin.py b/com/admin.py index 7e31cd52..2b31a572 100644 --- a/com/admin.py +++ b/com/admin.py @@ -1,4 +1,3 @@ -# -*- coding:utf-8 -* # # Copyright 2023 © AE UTBM # ae@utbm.fr / ae.info@utbm.fr diff --git a/com/migrations/0001_initial.py b/com/migrations/0001_initial.py index 4fbab584..6e78440d 100644 --- a/com/migrations/0001_initial.py +++ b/com/migrations/0001_initial.py @@ -1,4 +1,3 @@ -# -*- coding: utf-8 -*- from __future__ import unicode_literals from django.db import migrations, models diff --git a/com/migrations/0002_news_newsdate.py b/com/migrations/0002_news_newsdate.py index 51a378f3..f1445224 100644 --- a/com/migrations/0002_news_newsdate.py +++ b/com/migrations/0002_news_newsdate.py @@ -1,4 +1,3 @@ -# -*- coding: utf-8 -*- from __future__ import unicode_literals import django.db.models.deletion diff --git a/com/migrations/0003_auto_20170115_2300.py b/com/migrations/0003_auto_20170115_2300.py index a21196b3..bef54268 100644 --- a/com/migrations/0003_auto_20170115_2300.py +++ b/com/migrations/0003_auto_20170115_2300.py @@ -1,4 +1,3 @@ -# -*- coding: utf-8 -*- from __future__ import unicode_literals import django.db.models.deletion diff --git a/com/migrations/0004_auto_20171221_1614.py b/com/migrations/0004_auto_20171221_1614.py index 6b4d4d9d..54a23b54 100644 --- a/com/migrations/0004_auto_20171221_1614.py +++ b/com/migrations/0004_auto_20171221_1614.py @@ -1,4 +1,3 @@ -# -*- coding: utf-8 -*- from __future__ import unicode_literals import django.db.models.deletion diff --git a/com/migrations/0005_auto_20180318_2227.py b/com/migrations/0005_auto_20180318_2227.py index 9e041699..ef8c450b 100644 --- a/com/migrations/0005_auto_20180318_2227.py +++ b/com/migrations/0005_auto_20180318_2227.py @@ -1,4 +1,3 @@ -# -*- coding: utf-8 -*- from __future__ import unicode_literals from django.db import migrations, models diff --git a/com/migrations/0006_remove_sith_index_page.py b/com/migrations/0006_remove_sith_index_page.py index 13f264ad..7b1bd0e6 100644 --- a/com/migrations/0006_remove_sith_index_page.py +++ b/com/migrations/0006_remove_sith_index_page.py @@ -1,4 +1,3 @@ -# -*- coding: utf-8 -*- # Generated by Django 1.11.23 on 2019-08-18 17:00 from __future__ import unicode_literals diff --git a/com/models.py b/com/models.py index d7a31596..d9a4628c 100644 --- a/com/models.py +++ b/com/models.py @@ -1,4 +1,3 @@ -# -*- coding:utf-8 -* # # Copyright 2016,2017 # - Skia @@ -47,14 +46,14 @@ class Sith(models.Model): weekmail_destinations = models.TextField(_("weekmail destinations"), default="") version = utils.get_git_revision_short_hash() + def __str__(self): + return "⛩ Sith ⛩" + def is_owned_by(self, user): if user.is_anonymous: return False return user.is_com_admin - def __str__(self): - return "⛩ Sith ⛩" - NEWS_TYPES = [ ("NOTICE", _("Notice")), @@ -91,28 +90,11 @@ class News(models.Model): 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): return "%s: %s" % (self.type, self.title) def save(self, *args, **kwargs): - super(News, self).save(*args, **kwargs) + super().save(*args, **kwargs) for u in ( RealGroup.objects.filter(id=settings.SITH_GROUP_COM_ADMIN_ID) .first() @@ -125,6 +107,23 @@ class News(models.Model): param="1", ).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): count = ( @@ -186,6 +185,9 @@ class Weekmail(models.Model): class Meta: ordering = ["-id"] + def __str__(self): + return f"Weekmail {self.id} (sent: {self.sent}) - {self.title}" + def send(self): """ 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") - def __str__(self): - return "Weekmail %s (sent: %s) - %s" % (self.id, self.sent, self.title) - def is_owned_by(self, user): if user.is_anonymous: return False @@ -274,18 +273,21 @@ class WeekmailArticle(models.Model): ) 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): if user.is_anonymous: return False return user.is_com_admin - def __str__(self): - return "%s - %s (%s)" % (self.title, self.author, self.club) - class Screen(models.Model): name = models.CharField(_("name"), max_length=128) + def __str__(self): + return self.name + def active_posters(self): now = timezone.now() return self.posters.filter(is_moderated=True, date_begin__lte=now).filter( @@ -297,9 +299,6 @@ class Screen(models.Model): return False return user.is_com_admin - def __str__(self): - return "%s" % (self.name) - class Poster(models.Model): name = models.CharField( @@ -329,6 +328,9 @@ class Poster(models.Model): on_delete=models.CASCADE, ) + def __str__(self): + return self.name + def save(self, *args, **kwargs): if not self.is_moderated: for u in ( @@ -341,7 +343,7 @@ class Poster(models.Model): url=reverse("com:poster_moderate_list"), type="POSTER_MODERATION", ).save() - return super(Poster, self).save(*args, **kwargs) + return super().save(*args, **kwargs) def clean(self, *args, **kwargs): if self.date_end and self.date_begin > self.date_end: @@ -361,6 +363,3 @@ class Poster(models.Model): @property def page(self): return self.club.page - - def __str__(self): - return self.name diff --git a/com/tests.py b/com/tests.py index df374161..ee3ef978 100644 --- a/com/tests.py +++ b/com/tests.py @@ -1,4 +1,3 @@ -# -*- coding:utf-8 -* # # Copyright 2023 © AE UTBM # ae@utbm.fr / ae.info@utbm.fr diff --git a/com/urls.py b/com/urls.py index ca4ee41e..20323f0a 100644 --- a/com/urls.py +++ b/com/urls.py @@ -1,4 +1,3 @@ -# -*- coding:utf-8 -* # # Copyright 2023 © AE UTBM # ae@utbm.fr / ae.info@utbm.fr diff --git a/com/views.py b/com/views.py index 774d1c5f..646b25c2 100644 --- a/com/views.py +++ b/com/views.py @@ -1,4 +1,3 @@ -# -*- coding:utf-8 -* # # Copyright 2016,2017 # - Skia @@ -82,7 +81,7 @@ class PosterForm(forms.ModelForm): def __init__(self, *args, **kwargs): self.user = kwargs.pop("user", None) - super(PosterForm, self).__init__(*args, **kwargs) + super().__init__(*args, **kwargs) if self.user: if not self.user.is_com_admin: self.fields["club"].queryset = Club.objects.filter( @@ -145,7 +144,7 @@ class IsComAdminMixin(View): def dispatch(self, request, *args, **kwargs): if not request.user.is_com_admin: raise PermissionDenied - return super(IsComAdminMixin, self).dispatch(request, *args, **kwargs) + return super().dispatch(request, *args, **kwargs) class ComEditView(ComTabsMixin, CanEditPropMixin, UpdateView): @@ -199,7 +198,7 @@ class NewsForm(forms.ModelForm): automoderation = forms.BooleanField(label=_("Automoderation"), required=False) def clean(self): - self.cleaned_data = super(NewsForm, self).clean() + self.cleaned_data = super().clean() if self.cleaned_data["type"] != "NOTICE": if not self.cleaned_data["start_date"]: self.add_error( @@ -225,7 +224,7 @@ class NewsForm(forms.ModelForm): return self.cleaned_data def save(self): - ret = super(NewsForm, self).save() + ret = super().save() self.instance.dates.all().delete() if self.instance.type == "EVENT" or self.instance.type == "CALL": NewsDate( @@ -252,24 +251,10 @@ class NewsEditView(CanEditMixin, UpdateView): pk_url_kwarg = "news_id" def get_initial(self): - init = {} - try: - init["start_date"] = ( - self.object.dates.order_by("id") - .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 + news_date: NewsDate = self.object.dates.order_by("id").first() + if news_date is None: + return {"start_date": None, "end_date": None} + return {"start_date": news_date.start_date, "end_date": news_date.end_date} def post(self, request, *args, **kwargs): form = self.get_form() @@ -302,7 +287,7 @@ class NewsEditView(CanEditMixin, UpdateView): ), type="NEWS_MODERATION", ).save() - return super(NewsEditView, self).form_valid(form) + return super().form_valid(form) class NewsCreateView(CanCreateMixin, CreateView): @@ -312,10 +297,9 @@ class NewsCreateView(CanCreateMixin, CreateView): def get_initial(self): init = {"author": self.request.user} - try: - init["club"] = Club.objects.filter(id=self.request.GET["club"]).first() - except: - pass + if "club" not in self.request.GET: + return init + init["club"] = Club.objects.filter(id=self.request.GET["club"]).first() return init def post(self, request, *args, **kwargs): @@ -346,7 +330,7 @@ class NewsCreateView(CanCreateMixin, CreateView): url=reverse("com:news_admin_list"), type="NEWS_MODERATION", ).save() - return super(NewsCreateView, self).form_valid(form) + return super().form_valid(form) class NewsDeleteView(CanEditMixin, DeleteView): @@ -385,7 +369,7 @@ class NewsListView(CanViewMixin, ListView): queryset = News.objects.filter(is_moderated=True) def get_context_data(self, **kwargs): - kwargs = super(NewsListView, self).get_context_data(**kwargs) + kwargs = super().get_context_data(**kwargs) kwargs["NewsDate"] = NewsDate kwargs["timedelta"] = timedelta kwargs["birthdays"] = ( @@ -416,7 +400,7 @@ class WeekmailPreviewView(ComTabsMixin, QuickNotifMixin, CanEditPropMixin, Detai def dispatch(self, request, *args, **kwargs): self.bad_recipients = [] - return super(WeekmailPreviewView, self).dispatch(request, *args, **kwargs) + return super().dispatch(request, *args, **kwargs) def post(self, request, *args, **kwargs): self.object = self.get_object() @@ -437,14 +421,14 @@ class WeekmailPreviewView(ComTabsMixin, QuickNotifMixin, CanEditPropMixin, Detai u.preferences.receive_weekmail = False u.preferences.save() 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): return self.model.objects.filter(sent=False).order_by("-id").first() def get_context_data(self, **kwargs): """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["bad_recipients"] = self.bad_recipients return kwargs @@ -520,11 +504,11 @@ class WeekmailEditView(ComTabsMixin, QuickNotifMixin, CanEditPropMixin, UpdateVi art.rank = -1 art.save() 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): """Add orphan articles""" - kwargs = super(WeekmailEditView, self).get_context_data(**kwargs) + kwargs = super().get_context_data(**kwargs) kwargs["orphans"] = WeekmailArticle.objects.filter(weekmail=None) return kwargs @@ -561,22 +545,16 @@ class WeekmailArticleCreateView(QuickNotifMixin, CreateView): quick_notif_url_arg = "qn_weekmail_new_article" def get_initial(self): - init = {} - try: - init["club"] = Club.objects.filter(id=self.request.GET["club"]).first() - except: - pass - return init + if "club" not in self.request.GET: + return {} + return {"club": Club.objects.filter(id=self.request.GET.get("club")).first()} def post(self, request, *args, **kwargs): form = self.get_form() self.object = form.instance - form.is_valid() #  Valid a first time to populate club field - try: - m = form.instance.club.get_membership_for(request.user) - if m.role <= settings.SITH_MAXIMUM_FREE_ROLE: - raise - except: + form.is_valid() # Valid a first time to populate club field + m = form.instance.club.get_membership_for(request.user) + if m is None or m.role <= settings.SITH_MAXIMUM_FREE_ROLE: form.add_error( "club", ValidationError( @@ -592,7 +570,7 @@ class WeekmailArticleCreateView(QuickNotifMixin, CreateView): def form_valid(self, form): form.instance.author = self.request.user - return super(WeekmailArticleCreateView, self).form_valid(form) + return super().form_valid(form) class WeekmailArticleDeleteView(CanEditPropMixin, DeleteView): @@ -612,10 +590,10 @@ class MailingListAdminView(ComTabsMixin, ListView): def dispatch(self, request, *args, **kwargs): if not (request.user.is_com_admin or request.user.is_root): raise PermissionDenied - return super(MailingListAdminView, self).dispatch(request, *args, **kwargs) + return super().dispatch(request, *args, **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["unmoderated"] = self.get_queryset().filter(is_moderated=False).all() kwargs["has_moderated"] = len(kwargs["moderated"]) > 0 @@ -647,7 +625,7 @@ class PosterListBaseView(ListView): self.club = None if 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): if self.request.user.is_com_admin: @@ -656,7 +634,7 @@ class PosterListBaseView(ListView): return Poster.objects.filter(club=self.club.id) 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: kwargs["club"] = self.club return kwargs @@ -675,15 +653,15 @@ class PosterCreateBaseView(CreateView): def dispatch(self, request, *args, **kwargs): if "club_id" in kwargs: 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): - kwargs = super(PosterCreateBaseView, self).get_form_kwargs() + kwargs = super().get_form_kwargs() kwargs.update({"user": self.request.user}) return 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: kwargs["club"] = self.club return kwargs @@ -691,7 +669,7 @@ class PosterCreateBaseView(CreateView): def form_valid(self, form): if self.request.user.is_com_admin: form.instance.is_moderated = True - return super(PosterCreateBaseView, self).form_valid(form) + return super().form_valid(form) class PosterEditBaseView(UpdateView): @@ -718,20 +696,20 @@ class PosterEditBaseView(UpdateView): if "club_id" in kwargs and kwargs["club_id"]: try: self.club = Club.objects.get(pk=kwargs["club_id"]) - except Club.DoesNotExist: - raise PermissionDenied - return super(PosterEditBaseView, self).dispatch(request, *args, **kwargs) + except Club.DoesNotExist as e: + raise PermissionDenied from e + return super().dispatch(request, *args, **kwargs) def get_queryset(self): return Poster.objects.all() def get_form_kwargs(self): - kwargs = super(PosterEditBaseView, self).get_form_kwargs() + kwargs = super().get_form_kwargs() kwargs.update({"user": self.request.user}) return 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"): kwargs["club"] = self.club return kwargs @@ -739,7 +717,7 @@ class PosterEditBaseView(UpdateView): def form_valid(self, form): if self.request.user.is_com_admin: form.instance.is_moderated = False - return super(PosterEditBaseView, self).form_valid(form) + return super().form_valid(form) class PosterDeleteBaseView(DeleteView): @@ -754,16 +732,16 @@ class PosterDeleteBaseView(DeleteView): if "club_id" in kwargs and kwargs["club_id"]: try: self.club = Club.objects.get(pk=kwargs["club_id"]) - except Club.DoesNotExist: - raise PermissionDenied - return super(PosterDeleteBaseView, self).dispatch(request, *args, **kwargs) + except Club.DoesNotExist as e: + raise PermissionDenied from e + return super().dispatch(request, *args, **kwargs) class PosterListView(IsComAdminMixin, ComTabsMixin, PosterListBaseView): """List communication posters""" def get_context_data(self, **kwargs): - kwargs = super(PosterListView, self).get_context_data(**kwargs) + kwargs = super().get_context_data(**kwargs) kwargs["app"] = "com" return kwargs @@ -774,7 +752,7 @@ class PosterCreateView(IsComAdminMixin, ComTabsMixin, PosterCreateBaseView): success_url = reverse_lazy("com:poster_list") def get_context_data(self, **kwargs): - kwargs = super(PosterCreateView, self).get_context_data(**kwargs) + kwargs = super().get_context_data(**kwargs) kwargs["app"] = "com" return kwargs @@ -785,7 +763,7 @@ class PosterEditView(IsComAdminMixin, ComTabsMixin, PosterEditBaseView): success_url = reverse_lazy("com:poster_list") def get_context_data(self, **kwargs): - kwargs = super(PosterEditView, self).get_context_data(**kwargs) + kwargs = super().get_context_data(**kwargs) kwargs["app"] = "com" return kwargs @@ -805,7 +783,7 @@ class PosterModerateListView(IsComAdminMixin, ComTabsMixin, ListView): queryset = Poster.objects.filter(is_moderated=False).all() def get_context_data(self, **kwargs): - kwargs = super(PosterModerateListView, self).get_context_data(**kwargs) + kwargs = super().get_context_data(**kwargs) kwargs["app"] = "com" return kwargs @@ -844,7 +822,7 @@ class ScreenSlideshowView(DetailView): template_name = "com/screen_slideshow.jinja" 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() return kwargs diff --git a/core/__init__.py b/core/__init__.py index 0aa913c4..a098e7ba 100644 --- a/core/__init__.py +++ b/core/__init__.py @@ -1,4 +1,3 @@ -# -*- coding:utf-8 -* # # Copyright 2023 © AE UTBM # ae@utbm.fr / ae.info@utbm.fr diff --git a/core/admin.py b/core/admin.py index 8b202a30..b739a794 100644 --- a/core/admin.py +++ b/core/admin.py @@ -1,4 +1,3 @@ -# -*- coding:utf-8 -* # # Copyright 2023 © AE UTBM # ae@utbm.fr / ae.info@utbm.fr diff --git a/core/apps.py b/core/apps.py index 872f34ae..50ea2cee 100644 --- a/core/apps.py +++ b/core/apps.py @@ -1,4 +1,3 @@ -# -*- coding:utf-8 -* # # Copyright 2017 # - Skia diff --git a/core/lookups.py b/core/lookups.py index 15205194..ecd508a2 100644 --- a/core/lookups.py +++ b/core/lookups.py @@ -1,4 +1,3 @@ -# -*- coding:utf-8 -* # # Copyright 2023 © AE UTBM # ae@utbm.fr / ae.info@utbm.fr diff --git a/core/management/__init__.py b/core/management/__init__.py index 0aa913c4..a098e7ba 100644 --- a/core/management/__init__.py +++ b/core/management/__init__.py @@ -1,4 +1,3 @@ -# -*- coding:utf-8 -* # # Copyright 2023 © AE UTBM # ae@utbm.fr / ae.info@utbm.fr diff --git a/core/management/commands/__init__.py b/core/management/commands/__init__.py index 0aa913c4..a098e7ba 100644 --- a/core/management/commands/__init__.py +++ b/core/management/commands/__init__.py @@ -1,4 +1,3 @@ -# -*- coding:utf-8 -* # # Copyright 2023 © AE UTBM # ae@utbm.fr / ae.info@utbm.fr diff --git a/core/management/commands/check_front.py b/core/management/commands/check_front.py index b6e24479..6f7bfda7 100644 --- a/core/management/commands/check_front.py +++ b/core/management/commands/check_front.py @@ -24,11 +24,11 @@ class Command(BaseCommand): def handle(self, *args, **options): deps = settings.SITH_FRONT_DEP_VERSIONS - processes = dict( - (url, create_process(url)) + processes = { + url: create_process(url) for url in deps.keys() if parse_semver(deps[url]) is not None - ) + } for url, process in processes.items(): try: diff --git a/core/management/commands/check_fs.py b/core/management/commands/check_fs.py index a6fc9597..16764eb9 100644 --- a/core/management/commands/check_fs.py +++ b/core/management/commands/check_fs.py @@ -1,4 +1,3 @@ -# -*- coding:utf-8 -* # # Copyright 2018 # - Skia diff --git a/core/management/commands/compilemessages.py b/core/management/commands/compilemessages.py index 87f1b2de..ecd83299 100644 --- a/core/management/commands/compilemessages.py +++ b/core/management/commands/compilemessages.py @@ -1,5 +1,4 @@ #!/usr/bin/env python3 -# -*- coding:utf-8 -* # # Copyright 2019 # - Sli @@ -41,4 +40,4 @@ class Command(compilemessages.Command): def handle(self, *args, **options): os.chdir("sith") - super(Command, self).handle(*args, **options) + super().handle(*args, **options) diff --git a/core/management/commands/compilestatic.py b/core/management/commands/compilestatic.py index f1268c23..8477c77d 100644 --- a/core/management/commands/compilestatic.py +++ b/core/management/commands/compilestatic.py @@ -1,5 +1,4 @@ #!/usr/bin/env python3 -# -*- coding:utf-8 -* # # Copyright 2017 # - Sli diff --git a/core/management/commands/documentation.py b/core/management/commands/documentation.py index bcaa0664..3e00d84b 100644 --- a/core/management/commands/documentation.py +++ b/core/management/commands/documentation.py @@ -1,5 +1,4 @@ #!/usr/bin/env python3 -# -*- coding:utf-8 -* # # Copyright 2019 # - Sli diff --git a/core/management/commands/install_xapian.py b/core/management/commands/install_xapian.py index 9181c151..e91491be 100644 --- a/core/management/commands/install_xapian.py +++ b/core/management/commands/install_xapian.py @@ -1,4 +1,3 @@ -# -*- coding:utf-8 -* # # Copyright 2024 © AE UTBM # ae@utbm.fr / ae.info@utbm.fr @@ -47,7 +46,7 @@ class Command(BaseCommand): pyproject = tomli.load(f) 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): print("No virtual environment detected, this command can't be used") return diff --git a/core/management/commands/markdown.py b/core/management/commands/markdown.py index 35941ec4..c8e21714 100644 --- a/core/management/commands/markdown.py +++ b/core/management/commands/markdown.py @@ -1,4 +1,3 @@ -# -*- coding:utf-8 -* # # Copyright 2017 # - Skia diff --git a/core/management/commands/populate.py b/core/management/commands/populate.py index d42d9987..d2f6c9dd 100644 --- a/core/management/commands/populate.py +++ b/core/management/commands/populate.py @@ -1,4 +1,3 @@ -# -*- coding:utf-8 -* # # Copyright 2016,2017,2023 # - Skia diff --git a/core/management/commands/repair_fs.py b/core/management/commands/repair_fs.py index 21408084..5c8cca6c 100644 --- a/core/management/commands/repair_fs.py +++ b/core/management/commands/repair_fs.py @@ -1,4 +1,3 @@ -# -*- coding:utf-8 -* # # Copyright 2018 # - Skia diff --git a/core/management/commands/setup.py b/core/management/commands/setup.py index 5c91e1e6..4f64d078 100644 --- a/core/management/commands/setup.py +++ b/core/management/commands/setup.py @@ -1,4 +1,3 @@ -# -*- coding:utf-8 -* # # Copyright 2023 © AE UTBM # ae@utbm.fr / ae.info@utbm.fr diff --git a/core/markdown.py b/core/markdown.py index 0abe1954..42726a74 100644 --- a/core/markdown.py +++ b/core/markdown.py @@ -1,4 +1,3 @@ -# -*- coding:utf-8 -* # # Copyright 2023 © AE UTBM # ae@utbm.fr / ae.info@utbm.fr @@ -22,8 +21,8 @@ from mistune import InlineGrammar, InlineLexer, Markdown, Renderer, escape, esca class SithRenderer(Renderer): - def file_link(self, id, suffix): - return reverse("core:file_detail", kwargs={"file_id": id}) + suffix + def file_link(self, pk, suffix): + return reverse("core:file_detail", kwargs={"file_id": pk}) + suffix def exposant(self, text): return """%s""" % text @@ -51,13 +50,11 @@ class SithRenderer(Renderer): if not width.endswith("%"): width += "px" style = "width: %s; " % width - try: - height = m.group(3) + height = m.group(3) + if height is not None: if not height.endswith("%"): height += "px" style += "height: %s; " % height - except: - pass else: params = None src = original_src @@ -158,12 +155,12 @@ class SithInlineLexer(InlineLexer): 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) + pk = 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) + return super()._process_link(m, link, title) renderer = SithRenderer(escape=True) diff --git a/core/middleware.py b/core/middleware.py index ddc6dea3..5f5c945b 100644 --- a/core/middleware.py +++ b/core/middleware.py @@ -1,4 +1,3 @@ -# -*- coding:utf-8 -* # # Copyright 2023 © AE UTBM # ae@utbm.fr / ae.info@utbm.fr @@ -69,5 +68,5 @@ class SignalRequestMiddleware: self.get_response = get_response def __call__(self, request): - setattr(_threadlocal, "request", request) + _threadlocal.request = request return self.get_response(request) diff --git a/core/migrations/0001_initial.py b/core/migrations/0001_initial.py index 57050f26..47cad8ad 100644 --- a/core/migrations/0001_initial.py +++ b/core/migrations/0001_initial.py @@ -1,4 +1,3 @@ -# -*- coding: utf-8 -*- from __future__ import unicode_literals import django.contrib.auth.models @@ -574,7 +573,7 @@ class Migration(migrations.Migration): managers=[("objects", core.models.RealGroupManager())], ), migrations.AlterUniqueTogether( - name="page", unique_together=set([("name", "parent")]) + name="page", unique_together={("name", "parent")} ), migrations.AddField( model_name="user", diff --git a/core/migrations/0002_auto_20160831_0144.py b/core/migrations/0002_auto_20160831_0144.py index 8fbd762a..553efe46 100644 --- a/core/migrations/0002_auto_20160831_0144.py +++ b/core/migrations/0002_auto_20160831_0144.py @@ -1,4 +1,3 @@ -# -*- coding: utf-8 -*- from __future__ import unicode_literals from django.db import migrations, models diff --git a/core/migrations/0003_auto_20160902_1914.py b/core/migrations/0003_auto_20160902_1914.py index 65f11d3a..636f082a 100644 --- a/core/migrations/0003_auto_20160902_1914.py +++ b/core/migrations/0003_auto_20160902_1914.py @@ -1,4 +1,3 @@ -# -*- coding: utf-8 -*- from __future__ import unicode_literals import django.core.validators diff --git a/core/migrations/0004_user_godfathers.py b/core/migrations/0004_user_godfathers.py index d4066cc5..863b99bb 100644 --- a/core/migrations/0004_user_godfathers.py +++ b/core/migrations/0004_user_godfathers.py @@ -1,4 +1,3 @@ -# -*- coding: utf-8 -*- from __future__ import unicode_literals from django.conf import settings diff --git a/core/migrations/0005_auto_20161105_1035.py b/core/migrations/0005_auto_20161105_1035.py index 6f7c487f..ce442b25 100644 --- a/core/migrations/0005_auto_20161105_1035.py +++ b/core/migrations/0005_auto_20161105_1035.py @@ -1,4 +1,3 @@ -# -*- coding: utf-8 -*- from __future__ import unicode_literals import django.db.models.deletion diff --git a/core/migrations/0006_auto_20161108_1703.py b/core/migrations/0006_auto_20161108_1703.py index 6fba0417..6a6c831f 100644 --- a/core/migrations/0006_auto_20161108_1703.py +++ b/core/migrations/0006_auto_20161108_1703.py @@ -1,4 +1,3 @@ -# -*- coding: utf-8 -*- from __future__ import unicode_literals from django.db import migrations, models diff --git a/core/migrations/0008_sithfile_asked_for_removal.py b/core/migrations/0008_sithfile_asked_for_removal.py index 300c799f..d6d09176 100644 --- a/core/migrations/0008_sithfile_asked_for_removal.py +++ b/core/migrations/0008_sithfile_asked_for_removal.py @@ -1,4 +1,3 @@ -# -*- coding: utf-8 -*- from __future__ import unicode_literals from django.db import migrations, models diff --git a/core/migrations/0009_auto_20161120_1155.py b/core/migrations/0009_auto_20161120_1155.py index aafb2c54..41bf540f 100644 --- a/core/migrations/0009_auto_20161120_1155.py +++ b/core/migrations/0009_auto_20161120_1155.py @@ -1,4 +1,3 @@ -# -*- coding: utf-8 -*- from __future__ import unicode_literals import django.db.models.deletion diff --git a/core/migrations/0010_sithfile_is_in_sas.py b/core/migrations/0010_sithfile_is_in_sas.py index d98116fd..3cd30f28 100644 --- a/core/migrations/0010_sithfile_is_in_sas.py +++ b/core/migrations/0010_sithfile_is_in_sas.py @@ -1,4 +1,3 @@ -# -*- coding: utf-8 -*- from __future__ import unicode_literals from django.db import migrations, models diff --git a/core/migrations/0011_auto_20161124_0848.py b/core/migrations/0011_auto_20161124_0848.py index 6475189e..76442f18 100644 --- a/core/migrations/0011_auto_20161124_0848.py +++ b/core/migrations/0011_auto_20161124_0848.py @@ -1,4 +1,3 @@ -# -*- coding: utf-8 -*- from __future__ import unicode_literals import django.utils.timezone diff --git a/core/migrations/0012_notification.py b/core/migrations/0012_notification.py index 245a38e3..c1daf212 100644 --- a/core/migrations/0012_notification.py +++ b/core/migrations/0012_notification.py @@ -1,4 +1,3 @@ -# -*- coding: utf-8 -*- from __future__ import unicode_literals import django.db.models.deletion diff --git a/core/migrations/0013_auto_20161209_2338.py b/core/migrations/0013_auto_20161209_2338.py index 2bb96256..14e758fd 100644 --- a/core/migrations/0013_auto_20161209_2338.py +++ b/core/migrations/0013_auto_20161209_2338.py @@ -1,4 +1,3 @@ -# -*- coding: utf-8 -*- from __future__ import unicode_literals from django.db import migrations, models diff --git a/core/migrations/0014_auto_20161210_0009.py b/core/migrations/0014_auto_20161210_0009.py index 8d4bbc6c..e510911a 100644 --- a/core/migrations/0014_auto_20161210_0009.py +++ b/core/migrations/0014_auto_20161210_0009.py @@ -1,4 +1,3 @@ -# -*- coding: utf-8 -*- from __future__ import unicode_literals from django.db import migrations, models diff --git a/core/migrations/0015_sithfile_moderator.py b/core/migrations/0015_sithfile_moderator.py index 4e2a438d..b6e5795d 100644 --- a/core/migrations/0015_sithfile_moderator.py +++ b/core/migrations/0015_sithfile_moderator.py @@ -1,4 +1,3 @@ -# -*- coding: utf-8 -*- from __future__ import unicode_literals import django.db.models.deletion diff --git a/core/migrations/0016_auto_20161212_1922.py b/core/migrations/0016_auto_20161212_1922.py index 72432467..388e6538 100644 --- a/core/migrations/0016_auto_20161212_1922.py +++ b/core/migrations/0016_auto_20161212_1922.py @@ -1,4 +1,3 @@ -# -*- coding: utf-8 -*- from __future__ import unicode_literals import django.db.models.deletion diff --git a/core/migrations/0017_auto_20161220_1626.py b/core/migrations/0017_auto_20161220_1626.py index bf076241..e2841a87 100644 --- a/core/migrations/0017_auto_20161220_1626.py +++ b/core/migrations/0017_auto_20161220_1626.py @@ -1,4 +1,3 @@ -# -*- coding: utf-8 -*- from __future__ import unicode_literals from django.db import migrations, models diff --git a/core/migrations/0018_auto_20161224_0211.py b/core/migrations/0018_auto_20161224_0211.py index 72f9a57d..64f0a5cc 100644 --- a/core/migrations/0018_auto_20161224_0211.py +++ b/core/migrations/0018_auto_20161224_0211.py @@ -1,4 +1,3 @@ -# -*- coding: utf-8 -*- from __future__ import unicode_literals from django.db import migrations, models diff --git a/core/migrations/0019_preferences_receive_weekmail.py b/core/migrations/0019_preferences_receive_weekmail.py index 3f4dfff1..f81f564b 100644 --- a/core/migrations/0019_preferences_receive_weekmail.py +++ b/core/migrations/0019_preferences_receive_weekmail.py @@ -1,4 +1,3 @@ -# -*- coding: utf-8 -*- from __future__ import unicode_literals from django.db import migrations, models diff --git a/core/migrations/0020_auto_20170324_0917.py b/core/migrations/0020_auto_20170324_0917.py index 219be979..69b73768 100644 --- a/core/migrations/0020_auto_20170324_0917.py +++ b/core/migrations/0020_auto_20170324_0917.py @@ -1,4 +1,3 @@ -# -*- coding: utf-8 -*- from __future__ import unicode_literals import django.core.validators diff --git a/core/migrations/0021_auto_20170822_1529.py b/core/migrations/0021_auto_20170822_1529.py index 1f5452b2..cc434c50 100644 --- a/core/migrations/0021_auto_20170822_1529.py +++ b/core/migrations/0021_auto_20170822_1529.py @@ -1,4 +1,3 @@ -# -*- coding: utf-8 -*- from __future__ import unicode_literals from django.db import migrations, models diff --git a/core/migrations/0022_auto_20170822_2232.py b/core/migrations/0022_auto_20170822_2232.py index ff924258..7b2258e9 100644 --- a/core/migrations/0022_auto_20170822_2232.py +++ b/core/migrations/0022_auto_20170822_2232.py @@ -1,4 +1,3 @@ -# -*- coding: utf-8 -*- from __future__ import unicode_literals from django.db import migrations, models diff --git a/core/migrations/0023_auto_20170902_1226.py b/core/migrations/0023_auto_20170902_1226.py index 9bfd01ed..0850b1c5 100644 --- a/core/migrations/0023_auto_20170902_1226.py +++ b/core/migrations/0023_auto_20170902_1226.py @@ -1,4 +1,3 @@ -# -*- coding: utf-8 -*- from __future__ import unicode_literals import django.db.models.deletion diff --git a/core/migrations/0024_auto_20170906_1317.py b/core/migrations/0024_auto_20170906_1317.py index 7d47989f..25cb4840 100644 --- a/core/migrations/0024_auto_20170906_1317.py +++ b/core/migrations/0024_auto_20170906_1317.py @@ -1,4 +1,3 @@ -# -*- coding: utf-8 -*- from __future__ import unicode_literals from django.db import migrations, models diff --git a/core/migrations/0025_auto_20170919_1521.py b/core/migrations/0025_auto_20170919_1521.py index f7bd278c..28f90c70 100644 --- a/core/migrations/0025_auto_20170919_1521.py +++ b/core/migrations/0025_auto_20170919_1521.py @@ -1,4 +1,3 @@ -# -*- coding: utf-8 -*- from __future__ import unicode_literals import django.core.validators diff --git a/core/migrations/0026_auto_20170926_1512.py b/core/migrations/0026_auto_20170926_1512.py index a1538b64..bc694d75 100644 --- a/core/migrations/0026_auto_20170926_1512.py +++ b/core/migrations/0026_auto_20170926_1512.py @@ -1,4 +1,3 @@ -# -*- coding: utf-8 -*- from __future__ import unicode_literals from django.db import migrations, models diff --git a/core/migrations/0027_gift.py b/core/migrations/0027_gift.py index ca8ce67b..53a14437 100644 --- a/core/migrations/0027_gift.py +++ b/core/migrations/0027_gift.py @@ -1,4 +1,3 @@ -# -*- coding: utf-8 -*- from __future__ import unicode_literals import django.db.models.deletion diff --git a/core/migrations/0028_auto_20171216_2044.py b/core/migrations/0028_auto_20171216_2044.py index 20bdad8a..f42bdbde 100644 --- a/core/migrations/0028_auto_20171216_2044.py +++ b/core/migrations/0028_auto_20171216_2044.py @@ -1,4 +1,3 @@ -# -*- coding: utf-8 -*- from __future__ import unicode_literals from django.db import migrations, models diff --git a/core/migrations/0029_auto_20180426_2013.py b/core/migrations/0029_auto_20180426_2013.py index c591f47b..bc86fb66 100644 --- a/core/migrations/0029_auto_20180426_2013.py +++ b/core/migrations/0029_auto_20180426_2013.py @@ -1,4 +1,3 @@ -# -*- coding: utf-8 -*- from __future__ import unicode_literals import django.db.models.deletion @@ -17,7 +16,7 @@ class Migration(migrations.Migration): field=models.ForeignKey( on_delete=django.db.models.deletion.CASCADE, verbose_name="owner group", - default=core.models.Page.get_default_owner_group, + default=core.models.get_default_owner_group, related_name="owned_page", to="core.Group", ), diff --git a/core/migrations/0030_auto_20190704_1500.py b/core/migrations/0030_auto_20190704_1500.py index d15f9a25..596ed348 100644 --- a/core/migrations/0030_auto_20190704_1500.py +++ b/core/migrations/0030_auto_20190704_1500.py @@ -1,4 +1,3 @@ -# -*- coding: utf-8 -*- # Generated by Django 1.11.20 on 2019-07-04 13:00 from __future__ import unicode_literals diff --git a/core/migrations/0031_auto_20190906_1615.py b/core/migrations/0031_auto_20190906_1615.py index d562ea8d..a195bef1 100644 --- a/core/migrations/0031_auto_20190906_1615.py +++ b/core/migrations/0031_auto_20190906_1615.py @@ -1,4 +1,3 @@ -# -*- coding: utf-8 -*- # Generated by Django 1.11.24 on 2019-09-06 14:15 from __future__ import unicode_literals diff --git a/core/migrations/0032_auto_20190909_0043.py b/core/migrations/0032_auto_20190909_0043.py index d1af6070..78d4d992 100644 --- a/core/migrations/0032_auto_20190909_0043.py +++ b/core/migrations/0032_auto_20190909_0043.py @@ -1,4 +1,3 @@ -# -*- coding: utf-8 -*- # Generated by Django 1.11.24 on 2019-09-08 22:43 from __future__ import unicode_literals diff --git a/core/models.py b/core/models.py index 4fba43c3..19e762db 100644 --- a/core/models.py +++ b/core/models.py @@ -1,4 +1,3 @@ -# -*- coding:utf-8 -* # # Copyright 2016,2017,2018 # - Skia @@ -60,12 +59,12 @@ from core import utils class RealGroupManager(AuthGroupManager): def get_queryset(self): - return super(RealGroupManager, self).get_queryset().filter(is_meta=False) + return super().get_queryset().filter(is_meta=False) class MetaGroupManager(AuthGroupManager): def get_queryset(self): - return super(MetaGroupManager, self).get_queryset().filter(is_meta=True) + return super().get_queryset().filter(is_meta=True) class Group(AuthGroup): @@ -120,7 +119,7 @@ class MetaGroup(Group): proxy = True def __init__(self, *args, **kwargs): - super(MetaGroup, self).__init__(*args, **kwargs) + super().__init__(*args, **kwargs) self.is_meta = True @cached_property @@ -548,7 +547,7 @@ class User(AbstractBaseUser): self._change_username(self.username) else: create = True - super(User, self).save(*args, **kwargs) + super().save(*args, **kwargs) def make_home(self): if self.home is None: @@ -746,7 +745,7 @@ class User(AbstractBaseUser): class AnonymousUser(AuthAnonymousUser): def __init__(self): - super(AnonymousUser, self).__init__() + super().__init__() @property def can_create_subscription(self): @@ -846,12 +845,15 @@ class Preferences(models.Model): _("get a notification for every refilling"), default=False ) - def get_display_name(self): - return self.user.get_display_name() + def __str__(self): + return f"Preferences of {self.user}" def get_absolute_url(self): return self.user.get_absolute_url() + def get_display_name(self): + return self.user.get_display_name() + def get_directory(instance, filename): return ".{0}/{1}".format(instance.get_parent_path(), filename) @@ -929,6 +931,31 @@ class SithFile(models.Model): class Meta: verbose_name = _("file") + def __str__(self): + return self.get_parent_path() + "/" + self.name + + def save(self, *args, **kwargs): + sas = SithFile.objects.filter(id=settings.SITH_SAS_ROOT_DIR_ID).first() + self.is_in_sas = sas in self.get_parent_list() or self == sas + copy_rights = False + if self.id is None: + copy_rights = True + super().save(*args, **kwargs) + if copy_rights: + self.copy_rights() + if self.is_in_sas: + for u in ( + RealGroup.objects.filter(id=settings.SITH_GROUP_SAS_ADMIN_ID) + .first() + .users.all() + ): + Notification( + user=u, + url=reverse("sas:moderation"), + type="SAS_MODERATION", + param="1", + ).save() + def can_be_managed_by(self, user: User) -> bool: """ Tell if the user can manage the file (edit, delete, etc.) or not. @@ -987,13 +1014,13 @@ class SithFile(models.Model): self.compressed.delete() if self.thumbnail: self.thumbnail.delete() - return super(SithFile, self).delete() + return super().delete() def clean(self): """ Cleans up the file """ - super(SithFile, self).clean() + super().clean() if "/" in self.name: raise ValidationError(_("Character '/' not authorized in name")) if self == self.parent: @@ -1034,35 +1061,13 @@ class SithFile(models.Model): if self.is_file and (self.file is None or self.file == ""): raise ValidationError(_("You must provide a file")) - def save(self, *args, **kwargs): - sas = SithFile.objects.filter(id=settings.SITH_SAS_ROOT_DIR_ID).first() - self.is_in_sas = sas in self.get_parent_list() or self == sas - copy_rights = False - if self.id is None: - copy_rights = True - super(SithFile, self).save(*args, **kwargs) - if copy_rights: - self.copy_rights() - if self.is_in_sas: - for u in ( - RealGroup.objects.filter(id=settings.SITH_GROUP_SAS_ADMIN_ID) - .first() - .users.all() - ): - Notification( - user=u, - url=reverse("sas:moderation"), - type="SAS_MODERATION", - param="1", - ).save() - - def apply_rights_recursively(self, only_folders=False): + def apply_rights_recursively(self, *, only_folders=False): children = self.children.all() if only_folders: children = children.filter(is_folder=True) for c in children: c.copy_rights() - c.apply_rights_recursively(only_folders) + c.apply_rights_recursively(only_folders=only_folders) def copy_rights(self): """Copy, if possible, the rights of the parent folder""" @@ -1156,7 +1161,7 @@ class SithFile(models.Model): if attr == "is_file": return not self.is_folder else: - return super(SithFile, self).__getattribute__(attr) + return super().__getattribute__(attr) @cached_property def as_picture(self): @@ -1190,9 +1195,6 @@ class SithFile(models.Model): def get_download_url(self): return reverse("core:download", kwargs={"file_id": self.id}) - def __str__(self): - return self.get_parent_path() + "/" + self.name - class LockError(Exception): """There was a lock error on the object""" @@ -1212,6 +1214,11 @@ class NotLocked(LockError): pass +# This function prevents generating migration upon settings change +def get_default_owner_group(): + return settings.SITH_GROUP_ROOT_ID + + class Page(models.Model): """ The page class to build a Wiki @@ -1251,10 +1258,6 @@ class Page(models.Model): # playing with a Page object, use get_full_name() instead! _full_name = models.CharField(_("page name"), max_length=255, blank=True) - # This function prevents generating migration upon settings change - def get_default_owner_group(): - return settings.SITH_GROUP_ROOT_ID - owner_group = models.ForeignKey( Group, related_name="owned_page", @@ -1287,6 +1290,38 @@ class Page(models.Model): ("change_prop_page", "Can change the page's properties (groups, ...)"), ) + def __str__(self): + return self.get_full_name() + + def save(self, *args, **kwargs): + """ + Performs some needed actions before and after saving a page in database + """ + locked = kwargs.pop("force_lock", False) + if not locked: + locked = self.is_locked() + if not locked: + raise NotLocked("The page is not locked and thus can not be saved") + self.full_clean() + if not self.id: + super().save( + *args, **kwargs + ) # Save a first time to correctly set _full_name + # This reset the _full_name just before saving to maintain a coherent field quicker for queries than the + # recursive method + # It also update all the children to maintain correct names + self._full_name = self.get_full_name() + for c in self.children.all(): + c.save() + super().save(*args, **kwargs) + self.unset_lock() + + def get_absolute_url(self): + """ + This is needed for black magic powered UpdateView's children + """ + return reverse("core:page", kwargs={"page_name": self._full_name}) + @staticmethod def get_page_by_full_name(name): """ @@ -1294,9 +1329,6 @@ class Page(models.Model): """ return Page.objects.filter(_full_name=name).first() - def __init__(self, *args, **kwargs): - super(Page, self).__init__(*args, **kwargs) - def clean(self): """ Cleans up only the name for the moment, but this can be used to make any treatment before saving the object @@ -1309,7 +1341,7 @@ class Page(models.Model): .exists() ): raise ValidationError(_("Duplicate page"), code="duplicate") - super(Page, self).clean() + super().clean() if self.parent is not None and self in self.get_parent_list(): raise ValidationError(_("Loop in page tree"), code="loop") @@ -1334,29 +1366,6 @@ class Page(models.Model): p = p.parent return l - def save(self, *args, **kwargs): - """ - Performs some needed actions before and after saving a page in database - """ - locked = kwargs.pop("force_lock", False) - if not locked: - locked = self.is_locked() - if not locked: - raise NotLocked("The page is not locked and thus can not be saved") - self.full_clean() - if not self.id: - super(Page, self).save( - *args, **kwargs - ) # Save a first time to correctly set _full_name - # This reset the _full_name just before saving to maintain a coherent field quicker for queries than the - # recursive method - # It also update all the children to maintain correct names - self._full_name = self.get_full_name() - for c in self.children.all(): - c.save() - super(Page, self).save(*args, **kwargs) - self.unset_lock() - def is_locked(self): """ Is True if the page is locked, False otherwise @@ -1382,7 +1391,7 @@ class Page(models.Model): raise AlreadyLocked("The page is already locked by someone else") self.lock_user = user self.lock_timeout = timezone.now() - super(Page, self).save() + super().save() # print("Locking page") def set_lock_recursive(self, user): @@ -1405,7 +1414,7 @@ class Page(models.Model): """Always try to unlock, even if there is no lock""" self.lock_user = None self.lock_timeout = None - super(Page, self).save() + super().save() # print("Unlocking page") def get_lock(self): @@ -1416,15 +1425,6 @@ class Page(models.Model): return self.lock_user raise NotLocked("The page is not locked and thus can not return its user") - def get_absolute_url(self): - """ - This is needed for black magic powered UpdateView's children - """ - return reverse("core:page", kwargs={"page_name": self._full_name}) - - def __str__(self): - return self.get_full_name() - def get_full_name(self): """ Computes the real full_name of the page based on its name and its parent's name @@ -1459,7 +1459,7 @@ class Page(models.Model): child.parent = self.parent child.save() child.unset_lock_recursive() - super(Page, self).delete() + super().delete() class PageRev(models.Model): @@ -1481,15 +1481,22 @@ class PageRev(models.Model): class Meta: ordering = ["date"] + def __str__(self): + return str(self.__dict__) + + def save(self, *args, **kwargs): + if self.revision is None: + self.revision = self.page.revisions.all().count() + 1 + super().save(*args, **kwargs) + # Don't forget to unlock, otherwise, people will have to wait for the page's timeout + self.page.unset_lock() + def get_absolute_url(self): """ This is needed for black magic powered UpdateView's children """ return reverse("core:page", kwargs={"page_name": self.page._full_name}) - def __str__(self): - return str(self.__dict__) - def __getattribute__(self, attr): if attr == "owner_group": return self.page.owner_group @@ -1505,13 +1512,6 @@ class PageRev(models.Model): def can_be_edited_by(self, user): return self.page.can_be_edited_by(user) - def save(self, *args, **kwargs): - if self.revision is None: - self.revision = self.page.revisions.all().count() + 1 - super(PageRev, self).save(*args, **kwargs) - # Don't forget to unlock, otherwise, people will have to wait for the page's timeout - self.page.unset_lock() - class Notification(models.Model): user = models.ForeignKey( @@ -1530,6 +1530,15 @@ class Notification(models.Model): return self.get_type_display() % self.param return self.get_type_display() + def save(self, *args, **kwargs): + if not self.id and self.type in settings.SITH_PERMANENT_NOTIFICATIONS: + old_notif = self.user.notifications.filter(type=self.type).last() + if old_notif: + old_notif.callback() + old_notif.save() + return + super().save(*args, **kwargs) + def callback(self): # Get the callback defined in settings to update existing # notifications @@ -1539,15 +1548,6 @@ class Notification(models.Model): mod = importlib.import_module(mod_name) getattr(mod, func_name)(self) - def save(self, *args, **kwargs): - if not self.id and self.type in settings.SITH_PERMANENT_NOTIFICATIONS: - old_notif = self.user.notifications.filter(type=self.type).last() - if old_notif: - old_notif.callback() - old_notif.save() - return - super(Notification, self).save(*args, **kwargs) - class Gift(models.Model): label = models.CharField(_("label"), max_length=255) @@ -1586,8 +1586,8 @@ class OperationLog(models.Model): _("operation type"), max_length=40, choices=settings.SITH_LOG_OPERATION_TYPE ) - def is_owned_by(self, user): - return user.is_root - def __str__(self): return "%s - %s - %s" % (self.operation_type, self.label, self.operator) + + def is_owned_by(self, user): + return user.is_root diff --git a/core/operations.py b/core/operations.py index 10882f22..dceae7ed 100644 --- a/core/operations.py +++ b/core/operations.py @@ -1,4 +1,3 @@ -# -*- coding:utf-8 -* # # Copyright 2016,2017 # - Sli @@ -47,4 +46,4 @@ class PsqlRunOnly(migrations.RunSQL): def _run_sql(self, schema_editor, sqls): if connection.vendor == "postgresql": - super(PsqlRunOnly, self)._run_sql(schema_editor, sqls) + super()._run_sql(schema_editor, sqls) diff --git a/core/scss/finder.py b/core/scss/finder.py index 0b62fab3..b4f5d9d8 100644 --- a/core/scss/finder.py +++ b/core/scss/finder.py @@ -1,5 +1,4 @@ #!/usr/bin/env python3 -# -*- coding:utf-8 -* # # Copyright 2016,2017 # - Sli @@ -48,7 +47,7 @@ class ScssFinder(FileSystemFinder): filesystem_storage.prefix = self.locations[0][0] self.storages[location] = filesystem_storage - def find(self, path, all=False): + def find(self, path, all=False): # noqa A002 (shadows the builtin `all` function) if path.endswith(".css"): - return super(ScssFinder, self).find(path, all) + return super().find(path, all) return [] diff --git a/core/scss/processor.py b/core/scss/processor.py index add5e042..a2c0f3e1 100644 --- a/core/scss/processor.py +++ b/core/scss/processor.py @@ -1,5 +1,4 @@ #!/usr/bin/env python3 -# -*- coding:utf-8 -* # # Copyright 2017 # - Sli diff --git a/core/scss/storage.py b/core/scss/storage.py index e24fd406..87ccd7a3 100644 --- a/core/scss/storage.py +++ b/core/scss/storage.py @@ -1,5 +1,4 @@ #!/usr/bin/env python3 -# -*- coding:utf-8 -* # # Copyright 2017 # - Sli @@ -34,7 +33,7 @@ class ScssFileStorage(FileSystemStorage): location = settings.STATIC_ROOT if base_url is None: base_url = settings.STATIC_URL - super(ScssFileStorage, self).__init__(location, base_url, *args, **kwargs) + super().__init__(location, base_url, *args, **kwargs) def find_file(path): diff --git a/core/search_indexes.py b/core/search_indexes.py index f2448adb..bef75922 100644 --- a/core/search_indexes.py +++ b/core/search_indexes.py @@ -1,4 +1,3 @@ -# -*- coding:utf-8 -* # # Copyright 2016,2017 # - Skia @@ -85,14 +84,10 @@ class IndexSignalProcessor(signals.BaseSignalProcessor): ) def handle_forum_message_meta_save(self, sender, instance, **kwargs): - super(IndexSignalProcessor, self).handle_save( - ForumMessage, instance.message, **kwargs - ) + super().handle_save(ForumMessage, instance.message, **kwargs) def handle_forum_message_meta_delete(self, sender, instance, **kwargs): - super(IndexSignalProcessor, self).handle_delete( - ForumMessage, instance.message, **kwargs - ) + super().handle_delete(ForumMessage, instance.message, **kwargs) class BigCharFieldIndex(indexes.CharField): @@ -102,9 +97,9 @@ class BigCharFieldIndex(indexes.CharField): """ def prepare(self, term): - return bytes(super(BigCharFieldIndex, self).prepare(term), "utf-8")[ - :245 - ].decode("utf-8", errors="ignore") + return bytes(super().prepare(term), "utf-8")[:245].decode( + "utf-8", errors="ignore" + ) class ForumMessageIndex(indexes.SearchIndex, indexes.Indexable): diff --git a/core/templatetags/__init__.py b/core/templatetags/__init__.py index 0aa913c4..a098e7ba 100644 --- a/core/templatetags/__init__.py +++ b/core/templatetags/__init__.py @@ -1,4 +1,3 @@ -# -*- coding:utf-8 -* # # Copyright 2023 © AE UTBM # ae@utbm.fr / ae.info@utbm.fr diff --git a/core/templatetags/renderer.py b/core/templatetags/renderer.py index 86bd6791..cca2f290 100644 --- a/core/templatetags/renderer.py +++ b/core/templatetags/renderer.py @@ -1,4 +1,3 @@ -# -*- coding:utf-8 -* # # Copyright 2016,2017 # - Skia @@ -44,14 +43,16 @@ def markdown(text): @register.filter(name="phonenumber") -def phonenumber(value, country="FR", format=phonenumbers.PhoneNumberFormat.NATIONAL): +def phonenumber( + value, country="FR", number_format=phonenumbers.PhoneNumberFormat.NATIONAL +): """ This filter is kindly borrowed from https://github.com/foundertherapy/django-phonenumber-filter """ value = str(value) try: parsed = phonenumbers.parse(value, country) - return phonenumbers.format_number(parsed, format) + return phonenumbers.format_number(parsed, number_format) except phonenumbers.NumberParseException as e: return value diff --git a/core/tests.py b/core/tests.py index 733c0c38..bb78f4b6 100644 --- a/core/tests.py +++ b/core/tests.py @@ -1,4 +1,3 @@ -# -*- coding:utf-8 -* # # Copyright 2023 © AE UTBM # ae@utbm.fr / ae.info@utbm.fr diff --git a/core/urls.py b/core/urls.py index 3f6398e8..709346e4 100644 --- a/core/urls.py +++ b/core/urls.py @@ -1,4 +1,3 @@ -# -*- coding:utf-8 -* # # Copyright 2016,2017 # - Skia diff --git a/core/utils.py b/core/utils.py index 427786fe..01d833a5 100644 --- a/core/utils.py +++ b/core/utils.py @@ -1,4 +1,3 @@ -# -*- coding:utf-8 -* # # Copyright 2023 © AE UTBM # ae@utbm.fr / ae.info@utbm.fr @@ -106,7 +105,7 @@ def scale_dimension(width, height, long_edge): return int(width * ratio), int(height * ratio) -def resize_image(im, edge, format): +def resize_image(im, edge, img_format): (w, h) = im.size (width, height) = scale_dimension(w, h, long_edge=edge) content = BytesIO() @@ -115,7 +114,7 @@ def resize_image(im, edge, format): try: im.save( fp=content, - format=format.upper(), + format=img_format.upper(), quality=90, optimize=True, progressive=True, @@ -124,7 +123,7 @@ def resize_image(im, edge, format): PIL.ImageFile.MAXBLOCK = im.size[0] * im.size[1] im.save( fp=content, - format=format.upper(), + format=img_format.upper(), quality=90, optimize=True, progressive=True, @@ -203,14 +202,14 @@ def doku_to_markdown(text): quote_level = 0 for line in text.splitlines(): # Tables and quotes enter = re.finditer(r"\[quote(=(.+?))?\]", line) - quit = re.finditer(r"\[/quote\]", line) + quit_ = re.finditer(r"\[/quote\]", line) if re.search(r"\A\s*\^(([^\^]*?)\^)*", line): # Table part line = line.replace("^", "|") new_text.append("> " * quote_level + line) new_text.append( "> " * quote_level + "|---|" ) # Don't keep the text alignement in tables it's really too complex for what it's worth - elif enter or quit: # Quote part + elif enter or quit_: # Quote part for quote in enter: # Enter quotes (support multiple at a time) quote_level += 1 try: @@ -218,9 +217,9 @@ def doku_to_markdown(text): except: new_text.append("> " * quote_level) line = line.replace(quote.group(0), "") - final_quote_level = quote_level # Store quote_level to use at the end, since it will be modified during quit iteration + final_quote_level = quote_level # Store quote_level to use at the end, since it will be modified during quit_ iteration final_newline = False - for quote in quit: # Quit quotes (support multiple at a time) + for quote in quit_: # Quit quotes (support multiple at a time) line = line.replace(quote.group(0), "") quote_level -= 1 final_newline = True @@ -258,8 +257,8 @@ def bbcode_to_markdown(text): quote_level = 0 for line in text.splitlines(): # Tables and quotes enter = re.finditer(r"\[quote(=(.+?))?\]", line) - quit = re.finditer(r"\[/quote\]", line) - if enter or quit: # Quote part + quit_ = re.finditer(r"\[/quote\]", line) + if enter or quit_: # Quote part for quote in enter: # Enter quotes (support multiple at a time) quote_level += 1 try: @@ -267,9 +266,9 @@ def bbcode_to_markdown(text): except: new_text.append("> " * quote_level) line = line.replace(quote.group(0), "") - final_quote_level = quote_level # Store quote_level to use at the end, since it will be modified during quit iteration + final_quote_level = quote_level # Store quote_level to use at the end, since it will be modified during quit_ iteration final_newline = False - for quote in quit: # Quit quotes (support multiple at a time) + for quote in quit_: # Quit quotes (support multiple at a time) line = line.replace(quote.group(0), "") quote_level -= 1 final_newline = True diff --git a/core/views/__init__.py b/core/views/__init__.py index ad86fe2d..61665129 100644 --- a/core/views/__init__.py +++ b/core/views/__init__.py @@ -1,4 +1,3 @@ -# -*- coding:utf-8 -* # # Copyright 2016,2017 # - Skia @@ -44,26 +43,10 @@ from core.views.forms import LoginForm def forbidden(request, exception): - try: - return HttpResponseForbidden( - render( - request, - "core/403.jinja", - context={ - "next": request.path, - "form": LoginForm(), - "popup": request.resolver_match.kwargs["popup"] or "", - }, - ) - ) - except: - return HttpResponseForbidden( - render( - request, - "core/403.jinja", - context={"next": request.path, "form": LoginForm()}, - ) - ) + context = {"next": request.path, "form": LoginForm()} + if popup := request.resolver_match.kwargs.get("popup"): + context["popup"] = popup + return HttpResponseForbidden(render(request, "core/403.jinja", context=context)) def not_found(request, exception): @@ -161,9 +144,7 @@ class GenericContentPermissionMixinBuilder(View): self.object = self.get_object() if not self.get_permission_function(self.object, request.user): raise self.raised_error - return super(GenericContentPermissionMixinBuilder, self).dispatch( - request, *arg, **kwargs - ) + return super().dispatch(request, *arg, **kwargs) # If we get here, it's a ListView @@ -177,9 +158,7 @@ class GenericContentPermissionMixinBuilder(View): return self2._get_queryset().filter(id__in=l_id) self.get_queryset = types.MethodType(get_qs, self) - return super(GenericContentPermissionMixinBuilder, self).dispatch( - request, *arg, **kwargs - ) + return super().dispatch(request, *arg, **kwargs) class CanCreateMixin(View): @@ -191,7 +170,7 @@ class CanCreateMixin(View): """ def dispatch(self, request, *arg, **kwargs): - res = super(CanCreateMixin, self).dispatch(request, *arg, **kwargs) + res = super().dispatch(request, *arg, **kwargs) if not request.user.is_authenticated: raise PermissionDenied return res @@ -199,7 +178,7 @@ class CanCreateMixin(View): def form_valid(self, form): obj = form.instance if can_edit_prop(obj, self.request.user): - return super(CanCreateMixin, self).form_valid(form) + return super().form_valid(form) raise PermissionDenied @@ -258,7 +237,7 @@ class FormerSubscriberMixin(View): def dispatch(self, request, *args, **kwargs): if not request.user.was_subscribed: raise PermissionDenied - return super(FormerSubscriberMixin, self).dispatch(request, *args, **kwargs) + return super().dispatch(request, *args, **kwargs) class UserIsLoggedMixin(View): @@ -271,7 +250,7 @@ class UserIsLoggedMixin(View): def dispatch(self, request, *args, **kwargs): if request.user.is_anonymous: raise PermissionDenied - return super(UserIsLoggedMixin, self).dispatch(request, *args, **kwargs) + return super().dispatch(request, *args, **kwargs) class TabedViewMixin(View): @@ -280,25 +259,22 @@ class TabedViewMixin(View): """ def get_tabs_title(self): - try: + if hasattr(self, "tabs_title"): return self.tabs_title - except: - raise ImproperlyConfigured("tabs_title is required") + raise ImproperlyConfigured("tabs_title is required") def get_current_tab(self): - try: + if hasattr(self, "current_tab"): return self.current_tab - except: - raise ImproperlyConfigured("current_tab is required") + raise ImproperlyConfigured("current_tab is required") def get_list_of_tabs(self): - try: + if hasattr(self, "list_of_tabs"): return self.list_of_tabs - except: - raise ImproperlyConfigured("list_of_tabs is required") + raise ImproperlyConfigured("list_of_tabs is required") def get_context_data(self, **kwargs): - kwargs = super(TabedViewMixin, self).get_context_data(**kwargs) + kwargs = super().get_context_data(**kwargs) kwargs["tabs_title"] = self.get_tabs_title() kwargs["current_tab"] = self.get_current_tab() kwargs["list_of_tabs"] = self.get_list_of_tabs() @@ -311,22 +287,20 @@ class QuickNotifMixin: def dispatch(self, request, *arg, **kwargs): # In some cases, the class can stay instanciated, so we need to reset the list self.quick_notif_list = [] - return super(QuickNotifMixin, self).dispatch(request, *arg, **kwargs) + return super().dispatch(request, *arg, **kwargs) def get_success_url(self): - ret = super(QuickNotifMixin, self).get_success_url() - try: + ret = super().get_success_url() + if hasattr(self, "quick_notif_url_arg"): if "?" in ret: ret += "&" + self.quick_notif_url_arg else: ret += "?" + self.quick_notif_url_arg - except: - pass return ret def get_context_data(self, **kwargs): """Add quick notifications to context""" - kwargs = super(QuickNotifMixin, self).get_context_data(**kwargs) + kwargs = super().get_context_data(**kwargs) kwargs["quick_notifs"] = [] for n in self.quick_notif_list: kwargs["quick_notifs"].append(settings.SITH_QUICK_NOTIF[n]) @@ -353,7 +327,7 @@ class DetailFormView(SingleObjectMixin, FormView): """ Optimisation on group retrieval """ - return super(DetailFormView, self).get_object() + return super().get_object() from .files import * diff --git a/core/views/files.py b/core/views/files.py index 7cce06e7..b674267b 100644 --- a/core/views/files.py +++ b/core/views/files.py @@ -1,4 +1,3 @@ -# -*- coding:utf-8 -* # # Copyright 2023 © AE UTBM # ae@utbm.fr / ae.info@utbm.fr @@ -171,7 +170,7 @@ class FileListView(ListView): return SithFile.objects.filter(parent=None) def get_context_data(self, **kwargs): - kwargs = super(FileListView, self).get_context_data(**kwargs) + kwargs = super().get_context_data(**kwargs) kwargs["popup"] = "" if self.kwargs.get("popup") is not None: kwargs["popup"] = "popup" @@ -189,7 +188,7 @@ class FileEditView(CanEditMixin, UpdateView): if not self.object.can_be_managed_by(request.user): raise PermissionDenied - return super(FileEditView, self).get(request, *args, **kwargs) + return super().get(request, *args, **kwargs) def get_form_class(self): fields = ["name", "is_moderated"] @@ -207,7 +206,7 @@ class FileEditView(CanEditMixin, UpdateView): ) def get_context_data(self, **kwargs): - kwargs = super(FileEditView, self).get_context_data(**kwargs) + kwargs = super().get_context_data(**kwargs) kwargs["popup"] = "" if self.kwargs.get("popup") is not None: kwargs["popup"] = "popup" @@ -241,15 +240,15 @@ class FileEditPropView(CanEditPropMixin, UpdateView): if not self.object.can_be_managed_by(request.user): raise PermissionDenied - return super(FileEditPropView, self).get(request, *args, **kwargs) + return super().get(request, *args, **kwargs) def get_form(self, form_class=None): - form = super(FileEditPropView, self).get_form(form_class) + form = super().get_form(form_class) form.fields["parent"].queryset = SithFile.objects.filter(is_folder=True) return form def form_valid(self, form): - ret = super(FileEditPropView, self).form_valid(form) + ret = super().form_valid(form) if form.cleaned_data["recursive"]: self.object.apply_rights_recursively() return ret @@ -261,7 +260,7 @@ class FileEditPropView(CanEditPropMixin, UpdateView): ) def get_context_data(self, **kwargs): - kwargs = super(FileEditPropView, self).get_context_data(**kwargs) + kwargs = super().get_context_data(**kwargs) kwargs["popup"] = "" if self.kwargs.get("popup") is not None: kwargs["popup"] = "popup" @@ -277,7 +276,8 @@ class FileView(CanViewMixin, DetailView, FormMixin): context_object_name = "file" form_class = AddFilesForm - def handle_clipboard(request, object): + @staticmethod + def handle_clipboard(request, obj): """ This method handles the clipboard in the view. This method can fail, since it does not catch the exceptions coming from @@ -286,8 +286,8 @@ class FileView(CanViewMixin, DetailView, FormMixin): FileView.handle_clipboard(request, self.object) - `request` is usually the self.request object in your view - `object` is the SithFile object you want to put in the clipboard, or + `request` is usually the self.request obj in your view + `obj` is the SithFile object you want to put in the clipboard, or where you want to paste the clipboard """ if "delete" in request.POST.keys(): @@ -301,7 +301,7 @@ class FileView(CanViewMixin, DetailView, FormMixin): for f_id in request.POST.getlist("file_list"): f_id = int(f_id) if ( - f_id in [c.id for c in object.children.all()] + f_id in [c.id for c in obj.children.all()] and f_id not in request.session["clipboard"] ): request.session["clipboard"].append(f_id) @@ -309,7 +309,7 @@ class FileView(CanViewMixin, DetailView, FormMixin): for f_id in request.session["clipboard"]: sf = SithFile.objects.filter(id=f_id).first() if sf: - sf.move_to(object) + sf.move_to(obj) request.session["clipboard"] = [] request.session.modified = True @@ -320,7 +320,7 @@ class FileView(CanViewMixin, DetailView, FormMixin): if "clipboard" not in request.session.keys(): request.session["clipboard"] = [] - return super(FileView, self).get(request, *args, **kwargs) + return super().get(request, *args, **kwargs) def post(self, request, *args, **kwargs): self.object = self.get_object() @@ -328,7 +328,7 @@ class FileView(CanViewMixin, DetailView, FormMixin): request.session["clipboard"] = [] if request.user.can_edit(self.object): # XXX this call can fail! - FileView.handle_clipboard(request, self.object) + self.handle_clipboard(request, self.object) self.form = self.get_form() # The form handle only the file upload files = request.FILES.getlist("file_field") if ( @@ -338,7 +338,7 @@ class FileView(CanViewMixin, DetailView, FormMixin): ): self.form.process(parent=self.object, owner=request.user, files=files) if self.form.is_valid(): - return super(FileView, self).form_valid(self.form) + return super().form_valid(self.form) return self.form_invalid(self.form) def get_success_url(self): @@ -348,7 +348,7 @@ class FileView(CanViewMixin, DetailView, FormMixin): ) def get_context_data(self, **kwargs): - kwargs = super(FileView, self).get_context_data(**kwargs) + kwargs = super().get_context_data(**kwargs) kwargs["popup"] = "" kwargs["form"] = self.form if self.kwargs.get("popup") is not None: @@ -370,7 +370,7 @@ class FileDeleteView(CanEditPropMixin, DeleteView): if not self.object.can_be_managed_by(request.user): raise PermissionDenied - return super(FileDeleteView, self).get(request, *args, **kwargs) + return super().get(request, *args, **kwargs) def get_success_url(self): self.object.file.delete() # Doing it here or overloading delete() is the same, so let's do it here @@ -389,7 +389,7 @@ class FileDeleteView(CanEditPropMixin, DeleteView): ) def get_context_data(self, **kwargs): - kwargs = super(FileDeleteView, self).get_context_data(**kwargs) + kwargs = super().get_context_data(**kwargs) kwargs["popup"] = "" if self.kwargs.get("popup") is not None: kwargs["popup"] = "popup" @@ -400,7 +400,7 @@ class FileModerationView(TemplateView): template_name = "core/file_moderation.jinja" def get_context_data(self, **kwargs): - kwargs = super(FileModerationView, self).get_context_data(**kwargs) + kwargs = super().get_context_data(**kwargs) kwargs["files"] = SithFile.objects.filter(is_moderated=False)[:100] return kwargs diff --git a/core/views/forms.py b/core/views/forms.py index 5426ef14..1ee9bda2 100644 --- a/core/views/forms.py +++ b/core/views/forms.py @@ -1,4 +1,3 @@ -# -*- coding:utf-8 -* # # Copyright 2016,2017 # - Skia @@ -62,7 +61,7 @@ class SelectDateTime(DateTimeInput): attrs["class"] = "select_datetime" else: attrs = {"class": "select_datetime"} - return super(SelectDateTime, self).render(name, value, attrs, renderer) + return super().render(name, value, attrs, renderer) class SelectDate(DateInput): @@ -71,14 +70,14 @@ class SelectDate(DateInput): attrs["class"] = "select_date" else: attrs = {"class": "select_date"} - return super(SelectDate, self).render(name, value, attrs, renderer) + return super().render(name, value, attrs, renderer) class MarkdownInput(Textarea): template_name = "core/markdown_textarea.jinja" def get_context(self, name, value, attrs): - context = super(MarkdownInput, self).get_context(name, value, attrs) + context = super().get_context(name, value, attrs) context["statics"] = { "js": static("core/easymde/easymde.min.js"), @@ -118,7 +117,7 @@ class SelectFile(TextInput): output = ( '%(content)s
' % { - "content": super(SelectFile, self).render(name, value, attrs, renderer), + "content": super().render(name, value, attrs, renderer), "title": _("Choose file"), "name": name, } @@ -142,7 +141,7 @@ class SelectUser(TextInput): output = ( '%(content)s
' % { - "content": super(SelectUser, self).render(name, value, attrs, renderer), + "content": super().render(name, value, attrs, renderer), "title": _("Choose user"), "name": name, } @@ -182,7 +181,7 @@ class LoginForm(AuthenticationForm): except: pass kwargs["data"] = data - super(LoginForm, self).__init__(*arg, **kwargs) + super().__init__(*arg, **kwargs) self.fields["username"].label = _("Username, email, or account number") @@ -195,8 +194,8 @@ class RegisteringForm(UserCreationForm): model = User fields = ("first_name", "last_name", "email") - def save(self, commit=True): - user = super(RegisteringForm, self).save(commit=False) + def save(self, *, commit=True): + user = super().save(commit=False) user.set_password(self.cleaned_data["password1"]) user.generate_username() if commit: @@ -258,10 +257,10 @@ class UserProfileForm(forms.ModelForm): } def __init__(self, *arg, **kwargs): - super(UserProfileForm, self).__init__(*arg, **kwargs) + super().__init__(*arg, **kwargs) def full_clean(self): - super(UserProfileForm, self).full_clean() + super().full_clean() def generate_name(self, field_name, f): field_name = field_name[:-4] @@ -363,7 +362,7 @@ class PagePropForm(forms.ModelForm): ) def __init__(self, *arg, **kwargs): - super(PagePropForm, self).__init__(*arg, **kwargs) + super().__init__(*arg, **kwargs) self.fields["edit_groups"].required = False self.fields["view_groups"].required = False @@ -381,7 +380,7 @@ class PageForm(forms.ModelForm): ) def __init__(self, *args, **kwargs): - super(PageForm, self).__init__(*args, **kwargs) + super().__init__(*args, **kwargs) self.fields["parent"].queryset = ( self.fields["parent"] .queryset.exclude(name=settings.SITH_CLUB_ROOT_PAGE) @@ -398,7 +397,7 @@ class GiftForm(forms.ModelForm): def __init__(self, *args, **kwargs): user_id = kwargs.pop("user_id", None) - super(GiftForm, self).__init__(*args, **kwargs) + super().__init__(*args, **kwargs) if user_id: self.fields["user"].queryset = self.fields["user"].queryset.filter( id=user_id @@ -407,9 +406,9 @@ class GiftForm(forms.ModelForm): class TzAwareDateTimeField(forms.DateTimeField): - def __init__( - self, input_formats=["%Y-%m-%d %H:%M:%S"], widget=SelectDateTime, **kwargs - ): + def __init__(self, input_formats=None, widget=SelectDateTime, **kwargs): + if input_formats is None: + input_formats = ["%Y-%m-%d %H:%M:%S"] super().__init__(input_formats=input_formats, widget=widget, **kwargs) def prepare_value(self, value): @@ -420,7 +419,7 @@ class TzAwareDateTimeField(forms.DateTimeField): # attach it to the UTC timezone (so that to_current_timezone()) if not None # converts it to the local timezone) if value is not None: - value = timezone.make_aware(value, timezone.utc) + value = timezone.make_aware(value, datetime.timezone.utc) if isinstance(value, datetime.datetime): value = to_current_timezone(value) diff --git a/core/views/group.py b/core/views/group.py index 1c598832..70d5c3a4 100644 --- a/core/views/group.py +++ b/core/views/group.py @@ -1,4 +1,3 @@ -# -*- coding:utf-8 -* # # Copyright 2023 © AE UTBM # ae@utbm.fr / ae.info@utbm.fr @@ -38,7 +37,7 @@ class EditMembersForm(forms.Form): def __init__(self, *args, **kwargs): self.current_users = kwargs.pop("users", []) - super(EditMembersForm, self).__init__(*args, **kwargs) + super().__init__(*args, **kwargs) self.fields["users_removed"] = forms.ModelMultipleChoiceField( User.objects.filter(id__in=self.current_users).all(), label=_("Users to remove from group"), @@ -57,7 +56,7 @@ class EditMembersForm(forms.Form): """ Check that the user is not trying to add an user already in the group """ - cleaned_data = super(EditMembersForm, self).clean() + cleaned_data = super().clean() users_added = cleaned_data.get("users_added", None) if not users_added: return users_added @@ -120,7 +119,7 @@ class GroupTemplateView(CanEditMixin, DetailFormView): template_name = "core/group_detail.jinja" def form_valid(self, form): - resp = super(GroupTemplateView, self).form_valid(form) + resp = super().form_valid(form) data = form.clean() group = self.get_object() @@ -138,7 +137,7 @@ class GroupTemplateView(CanEditMixin, DetailFormView): ) def get_form_kwargs(self): - kwargs = super(GroupTemplateView, self).get_form_kwargs() + kwargs = super().get_form_kwargs() kwargs["users"] = self.get_object().users.all() return kwargs diff --git a/core/views/page.py b/core/views/page.py index 5f148235..fed0ac7f 100644 --- a/core/views/page.py +++ b/core/views/page.py @@ -1,4 +1,3 @@ -# -*- coding:utf-8 -* # # Copyright 2023 © AE UTBM # ae@utbm.fr / ae.info@utbm.fr @@ -29,7 +28,7 @@ from core.views.forms import MarkdownInput, PageForm, PagePropForm class CanEditPagePropMixin(CanEditPropMixin): def dispatch(self, request, *args, **kwargs): - res = super(CanEditPagePropMixin, self).dispatch(request, *args, **kwargs) + res = super().dispatch(request, *args, **kwargs) if self.object.is_club_page: raise Http404 return res @@ -45,7 +44,7 @@ class PageView(CanViewMixin, DetailView): template_name = "core/page_detail.jinja" def dispatch(self, request, *args, **kwargs): - res = super(PageView, self).dispatch(request, *args, **kwargs) + res = super().dispatch(request, *args, **kwargs) if self.object and self.object.need_club_redirection: return redirect("club:club_view", club_id=self.object.club.id) return res @@ -55,7 +54,7 @@ class PageView(CanViewMixin, DetailView): return self.page def get_context_data(self, **kwargs): - context = super(PageView, self).get_context_data(**kwargs) + context = super().get_context_data(**kwargs) if "page" not in context.keys(): context["new_page"] = self.kwargs["page_name"] return context @@ -66,7 +65,7 @@ class PageHistView(CanViewMixin, DetailView): template_name = "core/page_hist.jinja" def dispatch(self, request, *args, **kwargs): - res = super(PageHistView, self).dispatch(request, *args, **kwargs) + res = super().dispatch(request, *args, **kwargs) if self.object.need_club_redirection: return redirect("club:club_hist", club_id=self.object.club.id) return res @@ -81,7 +80,7 @@ class PageRevView(CanViewMixin, DetailView): template_name = "core/page_detail.jinja" def dispatch(self, request, *args, **kwargs): - res = super(PageRevView, self).dispatch(request, *args, **kwargs) + res = super().dispatch(request, *args, **kwargs) self.object = self.get_object() if self.object is None: @@ -98,7 +97,7 @@ class PageRevView(CanViewMixin, DetailView): return self.page def get_context_data(self, **kwargs): - context = super(PageRevView, self).get_context_data(**kwargs) + context = super().get_context_data(**kwargs) if self.page is not None: context["page"] = self.page try: @@ -129,13 +128,13 @@ class PageCreateView(CanCreateMixin, CreateView): return init def get_context_data(self, **kwargs): - context = super(PageCreateView, self).get_context_data(**kwargs) + context = super().get_context_data(**kwargs) context["new_page"] = True return context def form_valid(self, form): form.instance.set_lock(self.request.user) - ret = super(PageCreateView, self).form_valid(form) + ret = super().form_valid(form) return ret @@ -147,7 +146,7 @@ class PagePropView(CanEditPagePropMixin, UpdateView): slug_url_kwarg = "page_name" def get_object(self): - o = super(PagePropView, self).get_object() + o = super().get_object() # Create the page if it does not exists # if p == None: # parent_name = '/'.join(page_name.split('/')[:-1]) @@ -191,7 +190,7 @@ class PageEditViewBase(CanEditMixin, UpdateView): return None def get_context_data(self, **kwargs): - context = super(PageEditViewBase, self).get_context_data(**kwargs) + context = super().get_context_data(**kwargs) if self.page is not None: context["page"] = self.page else: @@ -205,12 +204,12 @@ class PageEditViewBase(CanEditMixin, UpdateView): new_rev.author = self.request.user new_rev.page = self.page form.instance = new_rev - return super(PageEditViewBase, self).form_valid(form) + return super().form_valid(form) class PageEditView(PageEditViewBase): def dispatch(self, request, *args, **kwargs): - res = super(PageEditView, self).dispatch(request, *args, **kwargs) + res = super().dispatch(request, *args, **kwargs) if self.object and self.object.page.need_club_redirection: return redirect("club:club_edit_page", club_id=self.object.page.club.id) return res diff --git a/core/views/site.py b/core/views/site.py index bdd575f4..67c628d8 100644 --- a/core/views/site.py +++ b/core/views/site.py @@ -1,4 +1,3 @@ -# -*- coding:utf-8 -* # # Copyright 2016,2017 # - Skia @@ -75,7 +74,7 @@ def notification(request, notif_id): return redirect("/") -def search_user(query, as_json=False): +def search_user(query): try: # slugify turns everything into ascii and every whitespace into - # it ends by removing duplicate - (so ' - ' will turn into '-') @@ -94,7 +93,7 @@ def search_user(query, as_json=False): return [] -def search_club(query, as_json=False): +def search_club(query, *, as_json=False): clubs = [] if query: clubs = Club.objects.filter(name__icontains=query).all() @@ -118,15 +117,15 @@ def search_view(request): @login_required def search_user_json(request): - result = {"users": search_user(request.GET.get("query", ""), True)} + result = {"users": search_user(request.GET.get("query", ""))} return JsonResponse(result) @login_required def search_json(request): result = { - "users": search_user(request.GET.get("query", ""), True), - "clubs": search_club(request.GET.get("query", ""), True), + "users": search_user(request.GET.get("query", "")), + "clubs": search_club(request.GET.get("query", ""), as_json=True), } return JsonResponse(result) @@ -144,7 +143,7 @@ class ToMarkdownView(TemplateView): return self.render_to_response(context) def get_context_data(self, **kwargs): - kwargs = super(ToMarkdownView, self).get_context_data(**kwargs) + kwargs = super().get_context_data(**kwargs) try: kwargs["text"] = self.text kwargs["text_md"] = self.text_md diff --git a/core/views/user.py b/core/views/user.py index d8d8d909..4c91b8ff 100644 --- a/core/views/user.py +++ b/core/views/user.py @@ -1,4 +1,3 @@ -# -*- coding:utf-8 -* # # Copyright 2016,2017 # - Skia @@ -294,7 +293,7 @@ class UserView(UserTabsMixin, CanViewMixin, DetailView): current_tab = "infos" def get_context_data(self, **kwargs): - kwargs = super(UserView, self).get_context_data(**kwargs) + kwargs = super().get_context_data(**kwargs) kwargs["gift_form"] = GiftForm( user_id=self.object.id, initial={"user": self.object} ) @@ -313,7 +312,7 @@ class UserPicturesView(UserTabsMixin, CanViewMixin, DetailView): current_tab = "pictures" def get_context_data(self, **kwargs): - kwargs = super(UserPicturesView, self).get_context_data(**kwargs) + kwargs = super().get_context_data(**kwargs) kwargs["albums"] = [] kwargs["pictures"] = {} picture_qs = all_pictures_of_user(self.object) @@ -363,10 +362,10 @@ class UserGodfathersView(UserTabsMixin, CanViewMixin, DetailView): self.object.godchildren.add(self.form.cleaned_data["user"]) self.object.save() self.form = UserGodfathersForm() - return super(UserGodfathersView, self).get(request, *args, **kwargs) + return super().get(request, *args, **kwargs) def get_context_data(self, **kwargs): - kwargs = super(UserGodfathersView, self).get_context_data(**kwargs) + kwargs = super().get_context_data(**kwargs) try: kwargs["form"] = self.form except: @@ -386,7 +385,7 @@ class UserGodfathersTreeView(UserTabsMixin, CanViewMixin, DetailView): current_tab = "godfathers" def get_context_data(self, **kwargs): - kwargs = super(UserGodfathersTreeView, self).get_context_data(**kwargs) + kwargs = super().get_context_data(**kwargs) if "descent" in self.request.GET: kwargs["param"] = "godchildren" else: @@ -496,10 +495,10 @@ class UserStatsView(UserTabsMixin, CanViewMixin, DetailView): ): raise PermissionDenied - return super(UserStatsView, self).dispatch(request, *arg, **kwargs) + return super().dispatch(request, *arg, **kwargs) def get_context_data(self, **kwargs): - kwargs = super(UserStatsView, self).get_context_data(**kwargs) + kwargs = super().get_context_data(**kwargs) from django.db.models import Sum from counter.models import Counter @@ -673,11 +672,11 @@ class UserUpdateProfileView(UserTabsMixin, CanEditMixin, UpdateView): and request.user.can_edit(self.object) and self.form.is_valid() ): - return super(UserUpdateProfileView, self).form_valid(self.form) + return super().form_valid(self.form) return self.form_invalid(self.form) def get_context_data(self, **kwargs): - kwargs = super(UserUpdateProfileView, self).get_context_data(**kwargs) + kwargs = super().get_context_data(**kwargs) kwargs["profile"] = self.form.instance kwargs["form"] = self.form return kwargs @@ -714,13 +713,13 @@ class UserPreferencesView(UserTabsMixin, CanEditMixin, UpdateView): return user def get_form_kwargs(self): - kwargs = super(UserPreferencesView, self).get_form_kwargs() + kwargs = super().get_form_kwargs() pref = self.object.preferences kwargs.update({"instance": pref}) return kwargs def get_context_data(self, **kwargs): - kwargs = super(UserPreferencesView, self).get_context_data(**kwargs) + kwargs = super().get_context_data(**kwargs) if not ( hasattr(self.object, "trombi_user") and self.request.user.trombi_user.trombi @@ -759,7 +758,7 @@ class UserToolsView(QuickNotifMixin, UserTabsMixin, UserIsLoggedMixin, TemplateV self.object = self.request.user from launderette.models import Launderette - kwargs = super(UserToolsView, self).get_context_data(**kwargs) + kwargs = super().get_context_data(**kwargs) kwargs["launderettes"] = Launderette.objects.all() kwargs["profile"] = self.request.user kwargs["object"] = self.request.user @@ -776,7 +775,7 @@ class UserAccountBase(UserTabsMixin, DetailView): current_tab = "account" def dispatch(self, request, *arg, **kwargs): # Manually validates the rights - res = super(UserAccountBase, self).dispatch(request, *arg, **kwargs) + res = super().dispatch(request, *arg, **kwargs) if ( self.object == request.user or request.user.is_in_group(pk=settings.SITH_GROUP_ACCOUNTING_ADMIN_ID) @@ -817,7 +816,7 @@ class UserAccountView(UserAccountBase): return t def get_context_data(self, **kwargs): - kwargs = super(UserAccountView, self).get_context_data(**kwargs) + kwargs = super().get_context_data(**kwargs) kwargs["profile"] = self.object try: kwargs["customer"] = self.object.customer @@ -846,7 +845,7 @@ class UserAccountDetailView(UserAccountBase, YearMixin, MonthMixin): template_name = "core/user_account_detail.jinja" def get_context_data(self, **kwargs): - kwargs = super(UserAccountDetailView, self).get_context_data(**kwargs) + kwargs = super().get_context_data(**kwargs) kwargs["profile"] = self.object kwargs["year"] = self.get_year() kwargs["month"] = self.get_month() @@ -866,13 +865,13 @@ class GiftCreateView(CreateView): if not (request.user.is_board_member or request.user.is_root): raise PermissionDenied self.user = get_object_or_404(User, pk=kwargs["user_id"]) - return super(GiftCreateView, self).dispatch(request, *args, **kwargs) + return super().dispatch(request, *args, **kwargs) def get_initial(self): return {"user": self.user} def get_form_kwargs(self): - kwargs = super(GiftCreateView, self).get_form_kwargs() + kwargs = super().get_form_kwargs() kwargs["user_id"] = self.user.id return kwargs @@ -887,7 +886,7 @@ class GiftDeleteView(CanEditPropMixin, DeleteView): def dispatch(self, request, *args, **kwargs): self.user = get_object_or_404(User, pk=kwargs["user_id"]) - return super(GiftDeleteView, self).dispatch(request, *args, **kwargs) + return super().dispatch(request, *args, **kwargs) def get_success_url(self): return reverse_lazy("core:user_profile", kwargs={"user_id": self.user.id}) diff --git a/counter/__init__.py b/counter/__init__.py index 5d5acce0..aeaae79e 100644 --- a/counter/__init__.py +++ b/counter/__init__.py @@ -1,4 +1,3 @@ -# -*- coding:utf-8 -* # # Copyright 2016,2017,2019 # - Skia diff --git a/counter/admin.py b/counter/admin.py index 1e8d9a03..8d5dcd33 100644 --- a/counter/admin.py +++ b/counter/admin.py @@ -1,4 +1,3 @@ -# -*- coding:utf-8 -* # # Copyright 2023 © AE UTBM # ae@utbm.fr / ae.info@utbm.fr diff --git a/counter/app.py b/counter/app.py index a1165d7c..47c81a01 100644 --- a/counter/app.py +++ b/counter/app.py @@ -1,4 +1,3 @@ -# -*- coding:utf-8 -* # # Copyright 2019 # - Sli diff --git a/counter/forms.py b/counter/forms.py index 7c282f57..1adbed68 100644 --- a/counter/forms.py +++ b/counter/forms.py @@ -18,7 +18,15 @@ from counter.models import ( class BillingInfoForm(forms.ModelForm): class Meta: model = BillingInfo - exclude = ["customer"] + fields = [ + "first_name", + "last_name", + "address_1", + "address_2", + "zip_code", + "city", + "country", + ] class StudentCardForm(forms.ModelForm): @@ -32,7 +40,7 @@ class StudentCardForm(forms.ModelForm): fields = ["uid"] def clean(self): - cleaned_data = super(StudentCardForm, self).clean() + cleaned_data = super().clean() uid = cleaned_data.get("uid", None) if not uid or not StudentCard.is_valid(uid): raise forms.ValidationError(_("This UID is invalid"), code="invalid") @@ -57,10 +65,10 @@ class GetUserForm(forms.Form): def as_p(self): self.fields["code"].widget.attrs["autofocus"] = True - return super(GetUserForm, self).as_p() + return super().as_p() def clean(self): - cleaned_data = super(GetUserForm, self).clean() + cleaned_data = super().clean() cus = None if cleaned_data["code"] != "": if len(cleaned_data["code"]) == StudentCard.UID_SIZE: @@ -141,14 +149,14 @@ class ProductEditForm(forms.ModelForm): ) def __init__(self, *args, **kwargs): - super(ProductEditForm, self).__init__(*args, **kwargs) + super().__init__(*args, **kwargs) if self.instance.id: self.fields["counters"].initial = [ str(c.id) for c in self.instance.counters.all() ] def save(self, *args, **kwargs): - ret = super(ProductEditForm, self).save(*args, **kwargs) + ret = super().save(*args, **kwargs) if self.fields["counters"].initial: for cid in self.fields["counters"].initial: c = Counter.objects.filter(id=int(cid)).first() diff --git a/counter/migrations/0001_initial.py b/counter/migrations/0001_initial.py index aa84e936..34381c89 100644 --- a/counter/migrations/0001_initial.py +++ b/counter/migrations/0001_initial.py @@ -1,4 +1,3 @@ -# -*- coding: utf-8 -*- from __future__ import unicode_literals import django.db.models.deletion diff --git a/counter/migrations/0002_auto_20160826_1342.py b/counter/migrations/0002_auto_20160826_1342.py index 83e6a83a..7655a480 100644 --- a/counter/migrations/0002_auto_20160826_1342.py +++ b/counter/migrations/0002_auto_20160826_1342.py @@ -1,4 +1,3 @@ -# -*- coding: utf-8 -*- from __future__ import unicode_literals import django.db.models.deletion diff --git a/counter/migrations/0003_permanency_activity.py b/counter/migrations/0003_permanency_activity.py index 915be8fc..21d59c62 100644 --- a/counter/migrations/0003_permanency_activity.py +++ b/counter/migrations/0003_permanency_activity.py @@ -1,4 +1,3 @@ -# -*- coding: utf-8 -*- from __future__ import unicode_literals import datetime diff --git a/counter/migrations/0004_auto_20160826_1907.py b/counter/migrations/0004_auto_20160826_1907.py index ce4d6180..62250b3a 100644 --- a/counter/migrations/0004_auto_20160826_1907.py +++ b/counter/migrations/0004_auto_20160826_1907.py @@ -1,4 +1,3 @@ -# -*- coding: utf-8 -*- from __future__ import unicode_literals from django.db import migrations, models diff --git a/counter/migrations/0005_auto_20160826_2330.py b/counter/migrations/0005_auto_20160826_2330.py index 9dc3fad9..1bf7c185 100644 --- a/counter/migrations/0005_auto_20160826_2330.py +++ b/counter/migrations/0005_auto_20160826_2330.py @@ -1,4 +1,3 @@ -# -*- coding: utf-8 -*- from __future__ import unicode_literals import django.db.models.deletion diff --git a/counter/migrations/0006_auto_20160831_1304.py b/counter/migrations/0006_auto_20160831_1304.py index 9ae1f4ec..48fbedc4 100644 --- a/counter/migrations/0006_auto_20160831_1304.py +++ b/counter/migrations/0006_auto_20160831_1304.py @@ -1,4 +1,3 @@ -# -*- coding: utf-8 -*- from __future__ import unicode_literals from django.db import migrations, models diff --git a/counter/migrations/0007_product_archived.py b/counter/migrations/0007_product_archived.py index 5dd3140d..85547692 100644 --- a/counter/migrations/0007_product_archived.py +++ b/counter/migrations/0007_product_archived.py @@ -1,4 +1,3 @@ -# -*- coding: utf-8 -*- from __future__ import unicode_literals from django.db import migrations, models diff --git a/counter/migrations/0008_counter_token.py b/counter/migrations/0008_counter_token.py index f8a5595e..bac8fa18 100644 --- a/counter/migrations/0008_counter_token.py +++ b/counter/migrations/0008_counter_token.py @@ -1,4 +1,3 @@ -# -*- coding: utf-8 -*- from __future__ import unicode_literals from django.db import migrations, models diff --git a/counter/migrations/0009_eticket.py b/counter/migrations/0009_eticket.py index 96d82e30..9a612262 100644 --- a/counter/migrations/0009_eticket.py +++ b/counter/migrations/0009_eticket.py @@ -1,4 +1,3 @@ -# -*- coding: utf-8 -*- from __future__ import unicode_literals import django.db.models.deletion diff --git a/counter/migrations/0010_auto_20161003_1900.py b/counter/migrations/0010_auto_20161003_1900.py index 91ed0756..c698d584 100644 --- a/counter/migrations/0010_auto_20161003_1900.py +++ b/counter/migrations/0010_auto_20161003_1900.py @@ -1,4 +1,3 @@ -# -*- coding: utf-8 -*- from __future__ import unicode_literals from django.db import migrations, models diff --git a/counter/migrations/0011_auto_20161004_2039.py b/counter/migrations/0011_auto_20161004_2039.py index 439cd354..90dd5740 100644 --- a/counter/migrations/0011_auto_20161004_2039.py +++ b/counter/migrations/0011_auto_20161004_2039.py @@ -1,4 +1,3 @@ -# -*- coding: utf-8 -*- from __future__ import unicode_literals from django.db import migrations, models diff --git a/counter/migrations/0012_auto_20170515_2202.py b/counter/migrations/0012_auto_20170515_2202.py index 2c11c82f..2930c505 100644 --- a/counter/migrations/0012_auto_20170515_2202.py +++ b/counter/migrations/0012_auto_20170515_2202.py @@ -1,4 +1,3 @@ -# -*- coding: utf-8 -*- from __future__ import unicode_literals from django.db import migrations, models diff --git a/counter/migrations/0013_customer_recorded_products.py b/counter/migrations/0013_customer_recorded_products.py index 271491eb..f2a48ba5 100644 --- a/counter/migrations/0013_customer_recorded_products.py +++ b/counter/migrations/0013_customer_recorded_products.py @@ -1,4 +1,3 @@ -# -*- coding: utf-8 -*- from __future__ import unicode_literals from django.conf import settings diff --git a/counter/migrations/0014_auto_20170816_1521.py b/counter/migrations/0014_auto_20170816_1521.py index 14c64d8d..0382f10c 100644 --- a/counter/migrations/0014_auto_20170816_1521.py +++ b/counter/migrations/0014_auto_20170816_1521.py @@ -1,4 +1,3 @@ -# -*- coding: utf-8 -*- from __future__ import unicode_literals from django.db import migrations, models diff --git a/counter/migrations/0014_auto_20170817_1537.py b/counter/migrations/0014_auto_20170817_1537.py index 8fef9833..30903684 100644 --- a/counter/migrations/0014_auto_20170817_1537.py +++ b/counter/migrations/0014_auto_20170817_1537.py @@ -1,4 +1,3 @@ -# -*- coding: utf-8 -*- from __future__ import unicode_literals from django.db import migrations, models diff --git a/counter/migrations/0015_merge.py b/counter/migrations/0015_merge.py index eba94807..5f5258a6 100644 --- a/counter/migrations/0015_merge.py +++ b/counter/migrations/0015_merge.py @@ -1,4 +1,3 @@ -# -*- coding: utf-8 -*- from __future__ import unicode_literals from django.db import migrations diff --git a/counter/migrations/0016_producttype_comment.py b/counter/migrations/0016_producttype_comment.py index ad5ad487..980c7fb0 100644 --- a/counter/migrations/0016_producttype_comment.py +++ b/counter/migrations/0016_producttype_comment.py @@ -1,4 +1,3 @@ -# -*- coding: utf-8 -*- from __future__ import unicode_literals from django.db import migrations, models diff --git a/counter/migrations/0017_studentcard.py b/counter/migrations/0017_studentcard.py index 267cef25..0f192c12 100644 --- a/counter/migrations/0017_studentcard.py +++ b/counter/migrations/0017_studentcard.py @@ -1,4 +1,3 @@ -# -*- coding: utf-8 -*- # Generated by Django 1.11.13 on 2018-10-18 23:15 from __future__ import unicode_literals diff --git a/counter/models.py b/counter/models.py index 44818da5..8d9db9b4 100644 --- a/counter/models.py +++ b/counter/models.py @@ -1,4 +1,3 @@ -# -*- coding:utf-8 -* # # Copyright 2023 © AE UTBM # ae@utbm.fr / ae.info@utbm.fr @@ -63,6 +62,19 @@ class Customer(models.Model): def __str__(self): return "%s - %s" % (self.user.username, self.account_id) + def save(self, *args, allow_negative=False, is_selling=False, **kwargs): + """ + is_selling : tell if the current action is a selling + allow_negative : ignored if not a selling. Allow a selling to put the account in negative + Those two parameters avoid blocking the save method of a customer if his account is negative + """ + if self.amount < 0 and (is_selling and not allow_negative): + raise ValidationError(_("Not enough money")) + super().save(*args, **kwargs) + + def get_absolute_url(self): + return reverse("core:user_account", kwargs={"user_id": self.user.pk}) + @property def can_record(self): return self.recorded_products > -settings.SITH_ECOCUP_LIMIT @@ -129,16 +141,6 @@ class Customer(models.Model): account = cls.objects.create(user=user, account_id=account_id) return account, True - def save(self, allow_negative=False, is_selling=False, *args, **kwargs): - """ - is_selling : tell if the current action is a selling - allow_negative : ignored if not a selling. Allow a selling to put the account in negative - Those two parameters avoid blocking the save method of a customer if his account is negative - """ - if self.amount < 0 and (is_selling and not allow_negative): - raise ValidationError(_("Not enough money")) - super(Customer, self).save(*args, **kwargs) - def recompute_amount(self): refillings = self.refillings.aggregate(sum=Sum(F("amount")))["sum"] self.amount = refillings if refillings is not None else 0 @@ -151,9 +153,6 @@ class Customer(models.Model): self.amount -= purchases self.save() - def get_absolute_url(self): - return reverse("core:user_account", kwargs={"user_id": self.user.pk}) - def get_full_url(self): return "".join(["https://", settings.SITH_URL, self.get_absolute_url()]) @@ -179,6 +178,9 @@ class BillingInfo(models.Model): city = models.CharField(_("City"), max_length=50) country = CountryField(blank_label=_("Country")) + def __str__(self): + return f"{self.first_name} {self.last_name}" + def to_3dsv2_xml(self) -> str: """ Convert the data from this model into a xml usable @@ -200,9 +202,6 @@ class BillingInfo(models.Model): xml = dict2xml(data, wrap="Billing", newlines=False) return '' + xml - def __str__(self): - return f"{self.first_name} {self.last_name}" - class ProductType(models.Model): """ @@ -223,6 +222,12 @@ class ProductType(models.Model): verbose_name = _("product type") ordering = ["-priority", "name"] + def __str__(self): + return self.name + + def get_absolute_url(self): + return reverse("counter:producttype_list") + def is_owned_by(self, user): """ Method to see if that object can be edited by the given user @@ -233,12 +238,6 @@ class ProductType(models.Model): return True return False - def __str__(self): - return self.name - - def get_absolute_url(self): - return reverse("counter:producttype_list") - class Product(models.Model): """ @@ -283,6 +282,12 @@ class Product(models.Model): class Meta: verbose_name = _("product") + def __str__(self): + return "%s (%s)" % (self.name, self.code) + + def get_absolute_url(self): + return reverse("counter:product_list") + @property def is_record_product(self): return settings.SITH_ECOCUP_CONS == self.id @@ -303,9 +308,6 @@ class Product(models.Model): return True return False - def get_absolute_url(self): - return reverse("counter:product_list") - def can_be_sold_to(self, user: User) -> bool: """ Check if whether the user given in parameter has the right to buy @@ -330,9 +332,6 @@ class Product(models.Model): def profit(self): return self.selling_price - self.purchase_price - def __str__(self): - return "%s (%s)" % (self.name, self.code) - class CounterQuerySet(models.QuerySet): def annotate_has_barman(self, user: User) -> CounterQuerySet: @@ -389,13 +388,6 @@ class Counter(models.Model): class Meta: verbose_name = _("counter") - def __getattribute__(self, name): - if name == "edit_groups": - return Group.objects.filter( - name=self.club.unix_name + settings.SITH_BOARD_SUFFIX - ).all() - return object.__getattribute__(self, name) - def __str__(self): return self.name @@ -404,6 +396,13 @@ class Counter(models.Model): return reverse("eboutic:main") return reverse("counter:details", kwargs={"counter_id": self.id}) + def __getattribute__(self, name): + if name == "edit_groups": + return Group.objects.filter( + name=self.club.unix_name + settings.SITH_BOARD_SUFFIX + ).all() + return object.__getattribute__(self, name) + def is_owned_by(self, user): if user.is_anonymous: return False @@ -630,16 +629,6 @@ class Refilling(models.Model): self.customer.user.get_display_name(), ) - def is_owned_by(self, user): - if user.is_anonymous: - return False - return user.is_owner(self.counter) and self.payment_method != "CARD" - - def delete(self, *args, **kwargs): - self.customer.amount -= self.amount - self.customer.save() - super(Refilling, self).delete(*args, **kwargs) - def save(self, *args, **kwargs): if not self.date: self.date = timezone.now() @@ -662,7 +651,17 @@ class Refilling(models.Model): param=str(self.amount), type="REFILLING", ).save() - super(Refilling, self).save(*args, **kwargs) + super().save(*args, **kwargs) + + def is_owned_by(self, user): + if user.is_anonymous: + return False + return user.is_owner(self.counter) and self.payment_method != "CARD" + + def delete(self, *args, **kwargs): + self.customer.amount -= self.amount + self.customer.save() + super().delete(*args, **kwargs) class Selling(models.Model): @@ -724,60 +723,7 @@ class Selling(models.Model): self.customer.user.get_display_name(), ) - def is_owned_by(self, user): - if user.is_anonymous: - return False - return user.is_owner(self.counter) and self.payment_method != "CARD" - - def can_be_viewed_by(self, user): - if ( - not hasattr(self, "customer") or self.customer is None - ): # Customer can be set to Null - return False - return user == self.customer.user - - def delete(self, *args, **kwargs): - if self.payment_method == "SITH_ACCOUNT": - self.customer.amount += self.quantity * self.unit_price - self.customer.save() - super(Selling, self).delete(*args, **kwargs) - - def send_mail_customer(self): - event = self.product.eticket.event_title or _("Unknown event") - subject = _("Eticket bought for the event %(event)s") % {"event": event} - message_html = _( - "You bought an eticket for the event %(event)s.\nYou can download it directly from this link %(eticket)s.\nYou can also retrieve all your e-tickets on your account page %(url)s." - ) % { - "event": event, - "url": "".join( - ( - '', - self.customer.get_full_url(), - "", - ) - ), - "eticket": "".join( - ( - '', - self.get_eticket_full_url(), - "", - ) - ), - } - message_txt = _( - "You bought an eticket for the event %(event)s.\nYou can download it directly from this link %(eticket)s.\nYou can also retrieve all your e-tickets on your account page %(url)s." - ) % { - "event": event, - "url": self.customer.get_full_url(), - "eticket": self.get_eticket_full_url(), - } - self.customer.user.email_user(subject, message_txt, html_message=message_html) - - def save(self, allow_negative=False, *args, **kwargs): + def save(self, *args, allow_negative=False, **kwargs): """ allow_negative : Allow this selling to use more money than available for this user """ @@ -851,7 +797,7 @@ class Selling(models.Model): param="%d x %s" % (self.quantity, self.label), type="SELLING", ).save() - super(Selling, self).save(*args, **kwargs) + super().save(*args, **kwargs) try: # The product has no id until it's saved if self.product.eticket: @@ -859,6 +805,59 @@ class Selling(models.Model): except: pass + def is_owned_by(self, user): + if user.is_anonymous: + return False + return user.is_owner(self.counter) and self.payment_method != "CARD" + + def can_be_viewed_by(self, user): + if ( + not hasattr(self, "customer") or self.customer is None + ): # Customer can be set to Null + return False + return user == self.customer.user + + def delete(self, *args, **kwargs): + if self.payment_method == "SITH_ACCOUNT": + self.customer.amount += self.quantity * self.unit_price + self.customer.save() + super().delete(*args, **kwargs) + + def send_mail_customer(self): + event = self.product.eticket.event_title or _("Unknown event") + subject = _("Eticket bought for the event %(event)s") % {"event": event} + message_html = _( + "You bought an eticket for the event %(event)s.\nYou can download it directly from this link %(eticket)s.\nYou can also retrieve all your e-tickets on your account page %(url)s." + ) % { + "event": event, + "url": "".join( + ( + '', + self.customer.get_full_url(), + "", + ) + ), + "eticket": "".join( + ( + '', + self.get_eticket_full_url(), + "", + ) + ), + } + message_txt = _( + "You bought an eticket for the event %(event)s.\nYou can download it directly from this link %(eticket)s.\nYou can also retrieve all your e-tickets on your account page %(url)s." + ) % { + "event": event, + "url": self.customer.get_full_url(), + "eticket": self.get_eticket_full_url(), + } + self.customer.user.email_user(subject, message_txt, html_message=message_html) + def get_eticket_full_url(self): eticket_url = reverse("counter:eticket_pdf", kwargs={"selling_id": self.id}) return "".join(["https://", settings.SITH_URL, eticket_url]) @@ -927,6 +926,14 @@ class CashRegisterSummary(models.Model): def __str__(self): return "At %s by %s - Total: %s €" % (self.counter, self.user, self.get_total()) + def save(self, *args, **kwargs): + if not self.id: + self.date = timezone.now() + return super().save(*args, **kwargs) + + def get_absolute_url(self): + return reverse("counter:cash_summary_list") + def __getattribute__(self, name): if name[:5] == "check": checks = self.items.filter(check=True).order_by("value").all() @@ -979,14 +986,6 @@ class CashRegisterSummary(models.Model): t += it.quantity * it.value return t - def save(self, *args, **kwargs): - if not self.id: - self.date = timezone.now() - return super(CashRegisterSummary, self).save(*args, **kwargs) - - def get_absolute_url(self): - return reverse("counter:cash_summary_list") - class CashRegisterSummaryItem(models.Model): cash_summary = models.ForeignKey( @@ -1006,6 +1005,9 @@ class CashRegisterSummaryItem(models.Model): class Meta: verbose_name = _("cash register summary item") + def __str__(self): + return str(self.value) + class Eticket(models.Model): """ @@ -1028,15 +1030,15 @@ class Eticket(models.Model): secret = models.CharField(_("secret"), max_length=64, unique=True) def __str__(self): - return "%s" % (self.product.name) - - def get_absolute_url(self): - return reverse("counter:eticket_list") + return self.product.name def save(self, *args, **kwargs): if not self.id: self.secret = base64.b64encode(os.urandom(32)) - return super(Eticket, self).save(*args, **kwargs) + return super().save(*args, **kwargs) + + def get_absolute_url(self): + return reverse("counter:eticket_list") def is_owned_by(self, user): """ @@ -1065,6 +1067,21 @@ class StudentCard(models.Model): UID_SIZE = 14 + uid = models.CharField( + _("uid"), max_length=UID_SIZE, unique=True, validators=[MinLengthValidator(4)] + ) + customer = models.ForeignKey( + Customer, + related_name="student_cards", + verbose_name=_("student cards"), + null=False, + blank=False, + on_delete=models.CASCADE, + ) + + def __str__(self): + return self.uid + @staticmethod def is_valid(uid): return ( @@ -1081,15 +1098,3 @@ class StudentCard(models.Model): if isinstance(obj, User): return StudentCard.can_create(self.customer, obj) return False - - uid = models.CharField( - _("uid"), max_length=14, unique=True, validators=[MinLengthValidator(4)] - ) - customer = models.ForeignKey( - Customer, - related_name="student_cards", - verbose_name=_("student cards"), - null=False, - blank=False, - on_delete=models.CASCADE, - ) diff --git a/counter/signals.py b/counter/signals.py index 9221494d..743f94f7 100644 --- a/counter/signals.py +++ b/counter/signals.py @@ -1,4 +1,3 @@ -# -*- coding:utf-8 -* # # Copyright 2019 # - Sli diff --git a/counter/tests.py b/counter/tests.py index ddfde22c..3754a842 100644 --- a/counter/tests.py +++ b/counter/tests.py @@ -1,4 +1,3 @@ -# -*- coding:utf-8 -* # # Copyright 2023 © AE UTBM # ae@utbm.fr / ae.info@utbm.fr diff --git a/counter/urls.py b/counter/urls.py index 3edf1faa..0c6e83f4 100644 --- a/counter/urls.py +++ b/counter/urls.py @@ -1,4 +1,3 @@ -# -*- coding:utf-8 -* # # Copyright 2023 © AE UTBM # ae@utbm.fr / ae.info@utbm.fr diff --git a/counter/views.py b/counter/views.py index e27547d2..7587df2f 100644 --- a/counter/views.py +++ b/counter/views.py @@ -1,4 +1,3 @@ -# -*- coding:utf-8 -* # # Copyright 2023 © AE UTBM # ae@utbm.fr / ae.info@utbm.fr @@ -102,7 +101,7 @@ class CounterAdminMixin(View): or self._test_club(request.user) ): raise PermissionDenied - return super(CounterAdminMixin, self).dispatch(request, *args, **kwargs) + return super().dispatch(request, *args, **kwargs) class StudentCardDeleteView(DeleteView, CanEditMixin): @@ -116,7 +115,7 @@ class StudentCardDeleteView(DeleteView, CanEditMixin): def dispatch(self, request, *args, **kwargs): self.customer = get_object_or_404(Customer, pk=kwargs["customer_id"]) - return super(StudentCardDeleteView, self).dispatch(request, *args, **kwargs) + return super().dispatch(request, *args, **kwargs) def get_success_url(self, **kwargs): return reverse_lazy( @@ -237,7 +236,7 @@ class CounterMain( ) + "?bad_location" ) - return super(CounterMain, self).post(request, *args, **kwargs) + return super().post(request, *args, **kwargs) def get_context_data(self, **kwargs): """ @@ -246,7 +245,7 @@ class CounterMain( if self.request.method == "POST": self.object = self.get_object() self.object.update_activity() - kwargs = super(CounterMain, self).get_context_data(**kwargs) + kwargs = super().get_context_data(**kwargs) kwargs["login_form"] = LoginForm() kwargs["login_form"].fields["username"].widget.attrs["autofocus"] = True kwargs[ @@ -280,7 +279,7 @@ class CounterMain( We handle here the redirection, passing the user id of the asked customer """ self.kwargs["user_id"] = form.cleaned_data["user_id"] - return super(CounterMain, self).form_valid(form) + return super().form_valid(form) def get_success_url(self): return reverse_lazy("counter:click", args=self.args, kwargs=self.kwargs) @@ -345,7 +344,7 @@ class CounterClick(CounterTabsMixin, CanViewMixin, DetailView): else: if not request.user.is_authenticated: raise PermissionDenied - return super(CounterClick, self).dispatch(request, *args, **kwargs) + return super().dispatch(request, *args, **kwargs) def get(self, request, *args, **kwargs): """Simple get view""" @@ -357,7 +356,7 @@ class CounterClick(CounterTabsMixin, CanViewMixin, DetailView): request.session["not_allowed"] = False request.session["no_age"] = False self.refill_form = None - ret = super(CounterClick, self).get(request, *args, **kwargs) + ret = super().get(request, *args, **kwargs) if (self.object.type != "BAR" and not request.user.is_authenticated) or ( self.object.type == "BAR" and len(self.object.get_barmen_list()) < 1 ): # Check that at least one barman is logged in @@ -435,7 +434,7 @@ class CounterClick(CounterTabsMixin, CanViewMixin, DetailView): def sum_basket(self, request): total = 0 - for pid, infos in request.session["basket"].items(): + for infos in request.session["basket"].values(): total += infos["price"] * infos["qty"] return total / 100 @@ -680,7 +679,7 @@ class CounterClick(CounterTabsMixin, CanViewMixin, DetailView): def get_context_data(self, **kwargs): """Add customer to the context""" - kwargs = super(CounterClick, self).get_context_data(**kwargs) + kwargs = super().get_context_data(**kwargs) products = self.object.products.select_related("product_type") if self.customer_is_barman(): products = products.annotate(price=F("special_selling_price")) @@ -732,7 +731,7 @@ class CounterLogin(RedirectView): self.errors += ["sellers"] else: self.errors += ["credentials"] - return super(CounterLogin, self).post(request, *args, **kwargs) + return super().post(request, *args, **kwargs) def get_redirect_url(self, *args, **kwargs): return ( @@ -752,7 +751,7 @@ class CounterLogout(RedirectView): self.counter = Counter.objects.filter(id=kwargs["counter_id"]).first() user = User.objects.filter(id=request.POST["user_id"]).first() self.counter.del_barman(user) - return super(CounterLogout, self).post(request, *args, **kwargs) + return super().post(request, *args, **kwargs) def get_redirect_url(self, *args, **kwargs): return reverse_lazy("counter:details", args=args, kwargs=kwargs) @@ -827,7 +826,7 @@ class CounterEditView(CounterAdminTabsMixin, CounterAdminMixin, UpdateView): def dispatch(self, request, *args, **kwargs): obj = self.get_object() self.edit_club.append(obj.club) - return super(CounterEditView, self).dispatch(request, *args, **kwargs) + return super().dispatch(request, *args, **kwargs) def get_success_url(self): return reverse_lazy("counter:admin", kwargs={"counter_id": self.object.id}) @@ -981,12 +980,12 @@ class RefillingDeleteView(DeleteView): self.success_url = reverse( "counter:details", kwargs={"counter_id": self.object.counter.id} ) - return super(RefillingDeleteView, self).dispatch(request, *args, **kwargs) + return super().dispatch(request, *args, **kwargs) elif self.object.is_owned_by(request.user): self.success_url = reverse( "core:user_account", kwargs={"user_id": self.object.customer.user.id} ) - return super(RefillingDeleteView, self).dispatch(request, *args, **kwargs) + return super().dispatch(request, *args, **kwargs) raise PermissionDenied @@ -1016,12 +1015,12 @@ class SellingDeleteView(DeleteView): self.success_url = reverse( "counter:details", kwargs={"counter_id": self.object.counter.id} ) - return super(SellingDeleteView, self).dispatch(request, *args, **kwargs) + return super().dispatch(request, *args, **kwargs) elif self.object.is_owned_by(request.user): self.success_url = reverse( "core:user_account", kwargs={"user_id": self.object.customer.user.id} ) - return super(SellingDeleteView, self).dispatch(request, *args, **kwargs) + return super().dispatch(request, *args, **kwargs) raise PermissionDenied @@ -1080,7 +1079,7 @@ class CashRegisterSummaryForm(forms.Form): def __init__(self, *args, **kwargs): instance = kwargs.pop("instance", None) - super(CashRegisterSummaryForm, self).__init__(*args, **kwargs) + super().__init__(*args, **kwargs) if instance: self.fields["ten_cents"].initial = ( instance.ten_cents.quantity if instance.ten_cents else 0 @@ -1261,9 +1260,7 @@ class CounterLastOperationsView(CounterTabsMixin, CanViewMixin, DetailView): token=request.session["counter_token"] ).exists() ): - return super(CounterLastOperationsView, self).dispatch( - request, *args, **kwargs - ) + return super().dispatch(request, *args, **kwargs) return HttpResponseRedirect( reverse("counter:details", kwargs={"counter_id": self.object.id}) + "?bad_location" @@ -1271,7 +1268,7 @@ class CounterLastOperationsView(CounterTabsMixin, CanViewMixin, DetailView): def get_context_data(self, **kwargs): """Add form to the context""" - kwargs = super(CounterLastOperationsView, self).get_context_data(**kwargs) + kwargs = super().get_context_data(**kwargs) threshold = timezone.now() - timedelta( minutes=settings.SITH_LAST_OPERATIONS_LIMIT ) @@ -1307,9 +1304,7 @@ class CounterCashSummaryView(CounterTabsMixin, CanViewMixin, DetailView): token=request.session["counter_token"] ).exists() ): - return super(CounterCashSummaryView, self).dispatch( - request, *args, **kwargs - ) + return super().dispatch(request, *args, **kwargs) return HttpResponseRedirect( reverse("counter:details", kwargs={"counter_id": self.object.id}) + "?bad_location" @@ -1318,7 +1313,7 @@ class CounterCashSummaryView(CounterTabsMixin, CanViewMixin, DetailView): def get(self, request, *args, **kwargs): self.object = self.get_object() self.form = CashRegisterSummaryForm() - return super(CounterCashSummaryView, self).get(request, *args, **kwargs) + return super().get(request, *args, **kwargs) def post(self, request, *args, **kwargs): self.object = self.get_object() @@ -1326,14 +1321,14 @@ class CounterCashSummaryView(CounterTabsMixin, CanViewMixin, DetailView): if self.form.is_valid(): self.form.save(self.object) return HttpResponseRedirect(self.get_success_url()) - return super(CounterCashSummaryView, self).get(request, *args, **kwargs) + return super().get(request, *args, **kwargs) def get_success_url(self): return reverse_lazy("counter:details", kwargs={"counter_id": self.object.id}) def get_context_data(self, **kwargs): """Add form to the context""" - kwargs = super(CounterCashSummaryView, self).get_context_data(**kwargs) + kwargs = super().get_context_data(**kwargs) kwargs["form"] = self.form return kwargs @@ -1362,7 +1357,7 @@ class CounterStatView(DetailView, CounterAdminMixin): counter: Counter = self.object semester_start = get_start_of_semester() office_hours = counter.get_top_barmen() - kwargs = super(CounterStatView, self).get_context_data(**kwargs) + kwargs = super().get_context_data(**kwargs) kwargs.update( { "counter": counter, @@ -1379,7 +1374,7 @@ class CounterStatView(DetailView, CounterAdminMixin): def dispatch(self, request, *args, **kwargs): try: - return super(CounterStatView, self).dispatch(request, *args, **kwargs) + return super().dispatch(request, *args, **kwargs) except PermissionDenied: if ( request.user.is_root @@ -1416,7 +1411,7 @@ class CashSummaryListView(CounterAdminTabsMixin, CounterAdminMixin, ListView): def get_context_data(self, **kwargs): """Add sums to the context""" - kwargs = super(CashSummaryListView, self).get_context_data(**kwargs) + kwargs = super().get_context_data(**kwargs) form = CashSummaryFormBase(self.request.GET) kwargs["form"] = form kwargs["summaries_sums"] = {} @@ -1467,7 +1462,7 @@ class InvoiceCallView(CounterAdminTabsMixin, CounterAdminMixin, TemplateView): def get_context_data(self, **kwargs): """Add sums to the context""" - kwargs = super(InvoiceCallView, self).get_context_data(**kwargs) + kwargs = super().get_context_data(**kwargs) kwargs["months"] = Selling.objects.datetimes("date", "month", order="DESC") start_date = None end_date = None @@ -1666,10 +1661,10 @@ class CounterRefillingListView(CounterAdminTabsMixin, CounterAdminMixin, ListVie def dispatch(self, request, *args, **kwargs): self.counter = get_object_or_404(Counter, pk=kwargs["counter_id"]) self.queryset = Refilling.objects.filter(counter__id=self.counter.id) - return super(CounterRefillingListView, self).dispatch(request, *args, **kwargs) + return super().dispatch(request, *args, **kwargs) def get_context_data(self, **kwargs): - kwargs = super(CounterRefillingListView, self).get_context_data(**kwargs) + kwargs = super().get_context_data(**kwargs) kwargs["counter"] = self.counter return kwargs @@ -1686,7 +1681,7 @@ class StudentCardFormView(FormView): self.customer = get_object_or_404(Customer, pk=kwargs["customer_id"]) if not StudentCard.can_create(self.customer, request.user): raise PermissionDenied - return super(StudentCardFormView, self).dispatch(request, *args, **kwargs) + return super().dispatch(request, *args, **kwargs) def form_valid(self, form): data = form.clean() @@ -1700,7 +1695,7 @@ class StudentCardFormView(FormView): ) -def __manage_billing_info_req(request, user_id, delete_if_fail=False): +def __manage_billing_info_req(request, user_id, *, delete_if_fail=False): data = json.loads(request.body) form = BillingInfoForm(data) if not form.is_valid(): @@ -1730,7 +1725,7 @@ def create_billing_info(request, user_id): user = get_object_or_404(User, pk=user_id) customer, _ = Customer.get_or_create(user) BillingInfo.objects.create(customer=customer) - return __manage_billing_info_req(request, user_id, True) + return __manage_billing_info_req(request, user_id, delete_if_fail=True) @login_required diff --git a/doc/conf.py b/doc/conf.py index d9f219c9..f43c1cc9 100644 --- a/doc/conf.py +++ b/doc/conf.py @@ -23,10 +23,10 @@ django.setup() # -- Project information ----------------------------------------------------- project = "Sith AE UTBM" -copyright = ( - "2019, Bartuccio Antoine (Sli), Brunet Pierre (Krohpil), Jacquet Florent (Skia)" +copyright = ( # noqa A001 + "2019, Bartuccio Antoine (Sli), Brunet Pierre (Krophil), Jacquet Florent (Skia)" ) -author = "Bartuccio Antoine (Sli), Brunet Pierre (Krohpil), Jacquet Florent (Skia)" +author = "Bartuccio Antoine (Sli), Brunet Pierre (Krophil), Jacquet Florent (Skia)" # -- General configuration --------------------------------------------------- diff --git a/eboutic/__init__.py b/eboutic/__init__.py index 0aa913c4..a098e7ba 100644 --- a/eboutic/__init__.py +++ b/eboutic/__init__.py @@ -1,4 +1,3 @@ -# -*- coding:utf-8 -* # # Copyright 2023 © AE UTBM # ae@utbm.fr / ae.info@utbm.fr diff --git a/eboutic/admin.py b/eboutic/admin.py index 84ca1afb..2455530d 100644 --- a/eboutic/admin.py +++ b/eboutic/admin.py @@ -1,4 +1,3 @@ -# -*- coding:utf-8 -* # # Copyright 2023 © AE UTBM # ae@utbm.fr / ae.info@utbm.fr diff --git a/eboutic/converters.py b/eboutic/converters.py index a757a25c..9da02f59 100644 --- a/eboutic/converters.py +++ b/eboutic/converters.py @@ -1,4 +1,3 @@ -# -*- coding:utf-8 -* # # Copyright 2022 # - Maréchal float: total = self.items.aggregate( total=Sum(F("quantity") * F("product_unit_price")) @@ -269,9 +271,6 @@ class Invoice(models.Model): self.validated = True self.save() - def __str__(self): - return "%s - %s - %s" % (self.user, self.get_total(), self.date) - class AbstractBaseItem(models.Model): product_id = models.IntegerField(_("product id")) diff --git a/eboutic/tests.py b/eboutic/tests.py index d99c8536..4657e748 100644 --- a/eboutic/tests.py +++ b/eboutic/tests.py @@ -1,4 +1,3 @@ -# -*- coding:utf-8 -* # # Copyright 2016,2017 # - Skia diff --git a/eboutic/tests/test.py b/eboutic/tests/test.py index 5527f116..908cd6c7 100755 --- a/eboutic/tests/test.py +++ b/eboutic/tests/test.py @@ -1,5 +1,4 @@ #!/usr/bin/env python3 -# -*- coding:utf-8 -* # # Skia < skia AT libskia DOT so > # diff --git a/eboutic/urls.py b/eboutic/urls.py index 22602aeb..704cdd6b 100644 --- a/eboutic/urls.py +++ b/eboutic/urls.py @@ -1,4 +1,3 @@ -# -*- coding:utf-8 -* # # Copyright 2016,2017, 2022 # - Skia diff --git a/eboutic/views.py b/eboutic/views.py index 8c39bf64..3ddc237d 100644 --- a/eboutic/views.py +++ b/eboutic/views.py @@ -1,4 +1,3 @@ -# -*- coding:utf-8 -* # # Copyright 2023 © AE UTBM # ae@utbm.fr / ae.info@utbm.fr diff --git a/election/migrations/0001_initial.py b/election/migrations/0001_initial.py index 04deb469..fda3bc6a 100644 --- a/election/migrations/0001_initial.py +++ b/election/migrations/0001_initial.py @@ -1,4 +1,3 @@ -# -*- coding: utf-8 -*- from __future__ import unicode_literals import django.db.models.deletion diff --git a/election/migrations/0002_election_archived.py b/election/migrations/0002_election_archived.py index 2b5ed86c..48cbace4 100644 --- a/election/migrations/0002_election_archived.py +++ b/election/migrations/0002_election_archived.py @@ -1,4 +1,3 @@ -# -*- coding: utf-8 -*- from __future__ import unicode_literals from django.db import migrations, models diff --git a/election/migrations/0003_auto_20171202_1819.py b/election/migrations/0003_auto_20171202_1819.py index 6cb48dc6..77d49758 100644 --- a/election/migrations/0003_auto_20171202_1819.py +++ b/election/migrations/0003_auto_20171202_1819.py @@ -1,4 +1,3 @@ -# -*- coding: utf-8 -*- from __future__ import unicode_literals from django.db import migrations, models diff --git a/election/models.py b/election/models.py index 3bcf761f..e52fe84e 100644 --- a/election/models.py +++ b/election/models.py @@ -99,7 +99,7 @@ class Election(models.Model): def delete(self, *args, **kwargs): self.election_lists.all().delete() - super(Election, self).delete(*args, **kwargs) + super().delete(*args, **kwargs) # Permissions @@ -163,16 +163,16 @@ class ElectionList(models.Model): on_delete=models.CASCADE, ) + def __str__(self): + return self.title + def can_be_edited_by(self, user): return user.can_edit(self.election) - def delete(self): + def delete(self, *args, **kwargs): for candidature in self.candidatures.all(): candidature.delete() - super(ElectionList, self).delete() - - def __str__(self): - return self.title + super().delete(*args, **kwargs) class Candidature(models.Model): @@ -201,17 +201,17 @@ class Candidature(models.Model): on_delete=models.CASCADE, ) + def __str__(self): + return f"{self.role.title} : {self.user.username}" + def delete(self): for vote in self.votes.all(): vote.delete() - super(Candidature, self).delete() + super().delete() def can_be_edited_by(self, user): return (user == self.user) or user.can_edit(self.role.election) - def __str__(self): - return "%s : %s" % (self.role.title, self.user.username) - class Vote(models.Model): """ diff --git a/election/views.py b/election/views.py index 71be8bfe..e2f412f3 100644 --- a/election/views.py +++ b/election/views.py @@ -27,10 +27,10 @@ class LimitedCheckboxField(forms.ModelMultipleChoiceField): def __init__(self, queryset, max_choice, **kwargs): self.max_choice = max_choice widget = forms.CheckboxSelectMultiple() - super(LimitedCheckboxField, self).__init__(queryset, **kwargs) + super().__init__(queryset, **kwargs) def clean(self, value): - qs = super(LimitedCheckboxField, self).clean(value) + qs = super().clean(value) self.validate(qs) return qs @@ -59,7 +59,7 @@ class CandidateForm(forms.ModelForm): def __init__(self, *args, **kwargs): election_id = kwargs.pop("election_id", None) can_edit = kwargs.pop("can_edit", False) - super(CandidateForm, self).__init__(*args, **kwargs) + super().__init__(*args, **kwargs) if election_id: self.fields["role"].queryset = Role.objects.filter( election__id=election_id @@ -73,7 +73,7 @@ class CandidateForm(forms.ModelForm): class VoteForm(forms.Form): def __init__(self, election, user, *args, **kwargs): - super(VoteForm, self).__init__(*args, **kwargs) + super().__init__(*args, **kwargs) if not election.has_voted(user): for role in election.roles.all(): cand = role.candidatures @@ -99,14 +99,14 @@ class RoleForm(forms.ModelForm): def __init__(self, *args, **kwargs): election_id = kwargs.pop("election_id", None) - super(RoleForm, self).__init__(*args, **kwargs) + super().__init__(*args, **kwargs) if election_id: self.fields["election"].queryset = Election.objects.filter( id=election_id ).all() def clean(self): - cleaned_data = super(RoleForm, self).clean() + cleaned_data = super().clean() title = cleaned_data.get("title") election = cleaned_data.get("election") if Role.objects.filter(title=title, election=election).exists(): @@ -122,7 +122,7 @@ class ElectionListForm(forms.ModelForm): def __init__(self, *args, **kwargs): election_id = kwargs.pop("election_id", None) - super(ElectionListForm, self).__init__(*args, **kwargs) + super().__init__(*args, **kwargs) if election_id: self.fields["election"].queryset = Election.objects.filter( id=election_id @@ -185,9 +185,7 @@ class ElectionsListView(CanViewMixin, ListView): template_name = "election/election_list.jinja" def get_queryset(self): - return ( - super(ElectionsListView, self).get_queryset().filter(archived=False).all() - ) + return super().get_queryset().filter(archived=False).all() class ElectionListArchivedView(CanViewMixin, ListView): @@ -201,12 +199,7 @@ class ElectionListArchivedView(CanViewMixin, ListView): template_name = "election/election_list.jinja" def get_queryset(self): - return ( - super(ElectionListArchivedView, self) - .get_queryset() - .filter(archived=True) - .all() - ) + return super().get_queryset().filter(archived=True).all() class ElectionDetailView(CanViewMixin, DetailView): @@ -219,7 +212,7 @@ class ElectionDetailView(CanViewMixin, DetailView): pk_url_kwarg = "election_id" def get(self, request, *arg, **kwargs): - response = super(ElectionDetailView, self).get(request, *arg, **kwargs) + response = super().get(request, *arg, **kwargs) election: Election = self.get_object() if request.user.can_edit(election) and election.is_vote_editable: action = request.GET.get("action", None) @@ -240,7 +233,7 @@ class ElectionDetailView(CanViewMixin, DetailView): def get_context_data(self, **kwargs): """Add additionnal data to the template""" - kwargs = super(ElectionDetailView, self).get_context_data(**kwargs) + kwargs = super().get_context_data(**kwargs) kwargs["election_form"] = VoteForm(self.object, self.request.user) kwargs["election_results"] = self.object.results return kwargs @@ -259,7 +252,7 @@ class VoteFormView(CanCreateMixin, FormView): def dispatch(self, request, *arg, **kwargs): self.election = get_object_or_404(Election, pk=kwargs["election_id"]) - return super(VoteFormView, self).dispatch(request, *arg, **kwargs) + return super().dispatch(request, *arg, **kwargs) def vote(self, election_data): with transaction.atomic(): @@ -279,7 +272,7 @@ class VoteFormView(CanCreateMixin, FormView): self.election.voters.add(self.request.user) def get_form_kwargs(self): - kwargs = super(VoteFormView, self).get_form_kwargs() + kwargs = super().get_form_kwargs() kwargs["election"] = self.election kwargs["user"] = self.request.user return kwargs @@ -301,7 +294,7 @@ class VoteFormView(CanCreateMixin, FormView): def get_context_data(self, **kwargs): """Add additionnal data to the template""" - kwargs = super(VoteFormView, self).get_context_data(**kwargs) + kwargs = super().get_context_data(**kwargs) kwargs["object"] = self.election kwargs["election"] = self.election kwargs["election_form"] = self.get_form() @@ -322,7 +315,7 @@ class CandidatureCreateView(CanCreateMixin, CreateView): def dispatch(self, request, *arg, **kwargs): self.election = get_object_or_404(Election, pk=kwargs["election_id"]) - return super(CandidatureCreateView, self).dispatch(request, *arg, **kwargs) + return super().dispatch(request, *arg, **kwargs) def get_initial(self): init = {} @@ -331,7 +324,7 @@ class CandidatureCreateView(CanCreateMixin, CreateView): return init def get_form_kwargs(self): - kwargs = super(CandidatureCreateView, self).get_form_kwargs() + kwargs = super().get_form_kwargs() kwargs["election_id"] = self.election.id kwargs["can_edit"] = self.can_edit return kwargs @@ -349,7 +342,7 @@ class CandidatureCreateView(CanCreateMixin, CreateView): raise PermissionDenied def get_context_data(self, **kwargs): - kwargs = super(CandidatureCreateView, self).get_context_data(**kwargs) + kwargs = super().get_context_data(**kwargs) kwargs["election"] = self.election return kwargs @@ -365,7 +358,7 @@ class ElectionCreateView(CanCreateMixin, CreateView): def dispatch(self, request, *args, **kwargs): if not request.user.is_subscribed: raise PermissionDenied - return super(ElectionCreateView, self).dispatch(request, *args, **kwargs) + return super().dispatch(request, *args, **kwargs) def form_valid(self, form): """ @@ -387,7 +380,7 @@ class RoleCreateView(CanCreateMixin, CreateView): self.election = get_object_or_404(Election, pk=kwargs["election_id"]) if not self.election.is_vote_editable: raise PermissionDenied - return super(RoleCreateView, self).dispatch(request, *arg, **kwargs) + return super().dispatch(request, *arg, **kwargs) def get_initial(self): init = {} @@ -407,7 +400,7 @@ class RoleCreateView(CanCreateMixin, CreateView): raise PermissionDenied def get_form_kwargs(self): - kwargs = super(RoleCreateView, self).get_form_kwargs() + kwargs = super().get_form_kwargs() kwargs["election_id"] = self.election.id return kwargs @@ -426,7 +419,7 @@ class ElectionListCreateView(CanCreateMixin, CreateView): self.election = get_object_or_404(Election, pk=kwargs["election_id"]) if not self.election.is_vote_editable: raise PermissionDenied - return super(ElectionListCreateView, self).dispatch(request, *arg, **kwargs) + return super().dispatch(request, *arg, **kwargs) def get_initial(self): init = {} @@ -434,7 +427,7 @@ class ElectionListCreateView(CanCreateMixin, CreateView): return init def get_form_kwargs(self): - kwargs = super(ElectionListCreateView, self).get_form_kwargs() + kwargs = super().get_form_kwargs() kwargs["election_id"] = self.election.id return kwargs @@ -506,7 +499,7 @@ class CandidatureUpdateView(CanEditMixin, UpdateView): self.object = self.get_object() if not self.object.role.election.is_vote_editable: raise PermissionDenied - return super(CandidatureUpdateView, self).dispatch(request, *arg, **kwargs) + return super().dispatch(request, *arg, **kwargs) def remove_fields(self): self.form.fields.pop("role", None) @@ -524,11 +517,11 @@ class CandidatureUpdateView(CanEditMixin, UpdateView): and request.user.can_edit(self.object) and self.form.is_valid() ): - return super(CandidatureUpdateView, self).form_valid(self.form) + return super().form_valid(self.form) return self.form_invalid(self.form) def get_form_kwargs(self): - kwargs = super(CandidatureUpdateView, self).get_form_kwargs() + kwargs = super().get_form_kwargs() kwargs["election_id"] = self.object.role.election.id return kwargs @@ -548,7 +541,7 @@ class RoleUpdateView(CanEditMixin, UpdateView): self.object = self.get_object() if not self.object.election.is_vote_editable: raise PermissionDenied - return super(RoleUpdateView, self).dispatch(request, *arg, **kwargs) + return super().dispatch(request, *arg, **kwargs) def remove_fields(self): self.form.fields.pop("election", None) @@ -568,11 +561,11 @@ class RoleUpdateView(CanEditMixin, UpdateView): and request.user.can_edit(self.object) and self.form.is_valid() ): - return super(RoleUpdateView, self).form_valid(self.form) + return super().form_valid(self.form) return self.form_invalid(self.form) def get_form_kwargs(self): - kwargs = super(RoleUpdateView, self).get_form_kwargs() + kwargs = super().get_form_kwargs() kwargs["election_id"] = self.object.election.id return kwargs @@ -592,7 +585,7 @@ class ElectionDeleteView(DeleteView): def dispatch(self, request, *args, **kwargs): if request.user.is_root: - return super(ElectionDeleteView, self).dispatch(request, *args, **kwargs) + return super().dispatch(request, *args, **kwargs) raise PermissionDenied def get_success_url(self, **kwargs): @@ -609,7 +602,7 @@ class CandidatureDeleteView(CanEditMixin, DeleteView): self.election = self.object.role.election if not self.election.can_candidate or not self.election.is_vote_editable: raise PermissionDenied - return super(CandidatureDeleteView, self).dispatch(request, *arg, **kwargs) + return super().dispatch(request, *arg, **kwargs) def get_success_url(self, **kwargs): return reverse_lazy("election:detail", kwargs={"election_id": self.election.id}) @@ -625,7 +618,7 @@ class RoleDeleteView(CanEditMixin, DeleteView): self.election = self.object.election if not self.election.is_vote_editable: raise PermissionDenied - return super(RoleDeleteView, self).dispatch(request, *arg, **kwargs) + return super().dispatch(request, *arg, **kwargs) def get_success_url(self, **kwargs): return reverse_lazy("election:detail", kwargs={"election_id": self.election.id}) @@ -641,7 +634,7 @@ class ElectionListDeleteView(CanEditMixin, DeleteView): self.election = self.object.election if not self.election.is_vote_editable: raise PermissionDenied - return super(ElectionListDeleteView, self).dispatch(request, *args, **kwargs) + return super().dispatch(request, *args, **kwargs) def get_success_url(self, **kwargs): return reverse_lazy("election:detail", kwargs={"election_id": self.election.id}) diff --git a/forum/__init__.py b/forum/__init__.py index 0aa913c4..a098e7ba 100644 --- a/forum/__init__.py +++ b/forum/__init__.py @@ -1,4 +1,3 @@ -# -*- coding:utf-8 -* # # Copyright 2023 © AE UTBM # ae@utbm.fr / ae.info@utbm.fr diff --git a/forum/admin.py b/forum/admin.py index eff7d401..a5deb07a 100644 --- a/forum/admin.py +++ b/forum/admin.py @@ -1,4 +1,3 @@ -# -*- coding:utf-8 -* # # Copyright 2023 © AE UTBM # ae@utbm.fr / ae.info@utbm.fr diff --git a/forum/migrations/0001_initial.py b/forum/migrations/0001_initial.py index 3d3440db..7b3d9624 100644 --- a/forum/migrations/0001_initial.py +++ b/forum/migrations/0001_initial.py @@ -1,4 +1,3 @@ -# -*- coding: utf-8 -*- from __future__ import unicode_literals import datetime diff --git a/forum/migrations/0002_auto_20170312_1753.py b/forum/migrations/0002_auto_20170312_1753.py index 2634d59e..92cdd3ae 100644 --- a/forum/migrations/0002_auto_20170312_1753.py +++ b/forum/migrations/0002_auto_20170312_1753.py @@ -1,4 +1,3 @@ -# -*- coding: utf-8 -*- from __future__ import unicode_literals from django.db import migrations, models diff --git a/forum/migrations/0003_auto_20170510_1754.py b/forum/migrations/0003_auto_20170510_1754.py index b708ae06..44c71cd4 100644 --- a/forum/migrations/0003_auto_20170510_1754.py +++ b/forum/migrations/0003_auto_20170510_1754.py @@ -1,4 +1,3 @@ -# -*- coding: utf-8 -*- from __future__ import unicode_literals from django.db import migrations, models diff --git a/forum/migrations/0004_auto_20170531_1949.py b/forum/migrations/0004_auto_20170531_1949.py index ef466a9b..9f21f770 100644 --- a/forum/migrations/0004_auto_20170531_1949.py +++ b/forum/migrations/0004_auto_20170531_1949.py @@ -1,4 +1,3 @@ -# -*- coding: utf-8 -*- from __future__ import unicode_literals import django.db.models.deletion diff --git a/forum/migrations/0005_forumtopic_subscribed_users.py b/forum/migrations/0005_forumtopic_subscribed_users.py index b977aadf..3db42e98 100644 --- a/forum/migrations/0005_forumtopic_subscribed_users.py +++ b/forum/migrations/0005_forumtopic_subscribed_users.py @@ -1,4 +1,3 @@ -# -*- coding: utf-8 -*- from __future__ import unicode_literals from django.conf import settings diff --git a/forum/migrations/0006_auto_20180426_2013.py b/forum/migrations/0006_auto_20180426_2013.py index 974b9b8e..029f407a 100644 --- a/forum/migrations/0006_auto_20180426_2013.py +++ b/forum/migrations/0006_auto_20180426_2013.py @@ -1,4 +1,3 @@ -# -*- coding: utf-8 -*- from __future__ import unicode_literals from django.db import migrations, models @@ -15,7 +14,7 @@ class Migration(migrations.Migration): name="edit_groups", field=models.ManyToManyField( blank=True, - default=forum.models.Forum.get_default_edit_group, + default=forum.models.get_default_edit_group, related_name="editable_forums", to="core.Group", ), @@ -25,7 +24,7 @@ class Migration(migrations.Migration): name="view_groups", field=models.ManyToManyField( blank=True, - default=forum.models.Forum.get_default_view_group, + default=forum.models.get_default_view_group, related_name="viewable_forums", to="core.Group", ), diff --git a/forum/models.py b/forum/models.py index a7d77c4d..92a233aa 100644 --- a/forum/models.py +++ b/forum/models.py @@ -1,4 +1,3 @@ -# -*- coding:utf-8 -* # # Copyright 2016,2017,2018 # - Skia @@ -21,6 +20,7 @@ # Place - Suite 330, Boston, MA 02111-1307, USA. # # +from __future__ import annotations from datetime import datetime from itertools import chain @@ -38,6 +38,15 @@ from club.models import Club from core.models import Group, User +# Those functions prevent generating migration upon settings changes +def get_default_edit_group(): + return [settings.SITH_GROUP_OLD_SUBSCRIBERS_ID] + + +def get_default_view_group(): + return [settings.SITH_GROUP_PUBLIC_ID] + + class Forum(models.Model): """ The Forum class, made as a tree to allow nice tidy organization @@ -47,13 +56,6 @@ class Forum(models.Model): view_groups allows some groups to view a forum """ - # Those functions prevent generating migration upon settings changes - def get_default_edit_group(): - return [settings.SITH_GROUP_OLD_SUBSCRIBERS_ID] - - def get_default_view_group(): - return [settings.SITH_GROUP_PUBLIC_ID] - id = models.AutoField(primary_key=True, db_index=True) name = models.CharField(_("name"), max_length=64) description = models.CharField(_("description"), max_length=512, default="") @@ -99,17 +101,23 @@ class Forum(models.Model): class Meta: ordering = ["number"] - def clean(self): - self.check_loop() + def __str__(self): + return self.name def save(self, *args, **kwargs): copy_rights = False if self.id is None: copy_rights = True - super(Forum, self).save(*args, **kwargs) + super().save(*args, **kwargs) if copy_rights: self.copy_rights() + def get_absolute_url(self): + return reverse("forum:view_forum", kwargs={"forum_id": self.id}) + + def clean(self): + self.check_loop() + def set_topic_number(self): self._topic_number = self.get_topic_number() self.save() @@ -167,11 +175,11 @@ class Forum(models.Model): return True try: m = Forum._club_memberships[self.id][user.id] - except: + except KeyError: m = self.owner_club.get_membership_for(user) try: Forum._club_memberships[self.id][user.id] = m - except: + except KeyError: Forum._club_memberships[self.id] = {} Forum._club_memberships[self.id][user.id] = m if m: @@ -188,9 +196,6 @@ class Forum(models.Model): objs.append(cur) cur = cur.parent - def __str__(self): - return "%s" % (self.name) - def get_full_name(self): return "/".join( chain.from_iterable( @@ -198,9 +203,6 @@ class Forum(models.Model): ) ) - def get_absolute_url(self): - return reverse("forum:view_forum", kwargs={"forum_id": self.id}) - @cached_property def parent_list(self): return self.get_parent_list() @@ -257,11 +259,17 @@ class ForumTopic(models.Model): class Meta: ordering = ["-_last_message__date"] + def __str__(self): + return self.title + def save(self, *args, **kwargs): - super(ForumTopic, self).save(*args, **kwargs) + super().save(*args, **kwargs) self.forum.set_topic_number() # Recompute the cached value self.forum.set_last_message() + def get_absolute_url(self): + return reverse("forum:view_topic", kwargs={"topic_id": self.id}) + def is_owned_by(self, user): return self.forum.is_owned_by(user) @@ -271,23 +279,15 @@ class ForumTopic(models.Model): def can_be_viewed_by(self, user): return user.can_view(self.forum) - def __str__(self): - return "%s" % (self.title) - - def get_absolute_url(self): - return reverse("forum:view_topic", kwargs={"topic_id": self.id}) - - def get_first_unread_message(self, user): - try: - msg = ( - self.messages.exclude(readers=user) - .filter(date__gte=user.forum_infos.last_read_date) - .order_by("id") - .first() - ) - return msg - except: + def get_first_unread_message(self, user: User) -> ForumMessage | None: + if not hasattr(user, "forum_infos"): return None + return ( + self.messages.exclude(readers=user) + .filter(date__gte=user.forum_infos.last_read_date) + .order_by("id") + .first() + ) @cached_property def last_message(self): @@ -325,7 +325,7 @@ class ForumMessage(models.Model): def save(self, *args, **kwargs): self._deleted = self.is_deleted() # Recompute the cached value - super(ForumMessage, self).save(*args, **kwargs) + super().save(*args, **kwargs) if self.is_last_in_topic(): self.topic._last_message_id = self.id if self.is_first_in_topic() and self.title: @@ -333,6 +333,9 @@ class ForumMessage(models.Model): self.topic._message_number = self.topic.messages.count() self.topic.save() + def get_absolute_url(self): + return reverse("forum:view_message", kwargs={"message_id": self.id}) + def is_first_in_topic(self): return bool(self.id == self.topic.messages.order_by("date").first().id) @@ -357,9 +360,6 @@ class ForumMessage(models.Model): def can_be_moderated_by(self, user): return self.topic.forum.is_owned_by(user) or user.id == self.author.id - def get_absolute_url(self): - return reverse("forum:view_message", kwargs={"message_id": self.id}) - def get_url(self): return ( self.topic.get_absolute_url() @@ -379,11 +379,10 @@ class ForumMessage(models.Model): ) def mark_as_read(self, user): - try: # Need the try/except because of AnonymousUser - if not self.is_read(user): - self.readers.add(user) - except: - pass + if user.is_anonymous: + return + if not self.is_read(user): + self.readers.add(user) def is_read(self, user): return (self.date < user.forum_infos.last_read_date) or ( @@ -414,8 +413,11 @@ class ForumMessageMeta(models.Model): date = models.DateTimeField(_("date"), default=timezone.now) action = models.CharField(_("action"), choices=MESSAGE_META_ACTIONS, max_length=16) + def __str__(self): + return f"{self.user.nick_name} ({self.date})" + def save(self, *args, **kwargs): - super(ForumMessageMeta, self).save(*args, **kwargs) + super().save(*args, **kwargs) self.message._deleted = self.message.is_deleted() self.message.save() diff --git a/forum/tests.py b/forum/tests.py index d888e761..48d8f1f6 100644 --- a/forum/tests.py +++ b/forum/tests.py @@ -1,4 +1,3 @@ -# -*- coding:utf-8 -* # # Copyright 2023 © AE UTBM # ae@utbm.fr / ae.info@utbm.fr diff --git a/forum/urls.py b/forum/urls.py index 8926ea01..f006f6a9 100644 --- a/forum/urls.py +++ b/forum/urls.py @@ -1,4 +1,3 @@ -# -*- coding:utf-8 -* # # Copyright 2016,2017,2018 # - Skia diff --git a/forum/views.py b/forum/views.py index 74e6bff4..93a19c49 100644 --- a/forum/views.py +++ b/forum/views.py @@ -1,4 +1,3 @@ -# -*- coding:utf-8 -* # # Copyright 2016,2017,2018 # - Skia @@ -22,12 +21,14 @@ # Place - Suite 330, Boston, MA 02111-1307, USA. # # +import math from ajax_select import make_ajax_field from django import forms from django.conf import settings from django.core.exceptions import PermissionDenied from django.core.paginator import EmptyPage, PageNotAnInteger, Paginator +from django.db import IntegrityError from django.shortcuts import get_object_or_404 from django.urls import reverse_lazy from django.utils import html, timezone @@ -104,15 +105,15 @@ class ForumMarkAllAsRead(RedirectView): url = reverse_lazy("forum:last_unread") def get(self, request, *args, **kwargs): + fi = request.user.forum_infos + fi.last_read_date = timezone.now() + fi.save() try: - fi = request.user.forum_infos - fi.last_read_date = timezone.now() - fi.save() for m in request.user.read_messages.filter(date__lt=fi.last_read_date): m.readers.remove(request.user) # Clean up to keep table low in data - except: + except IntegrityError: pass - return super(ForumMarkAllAsRead, self).get(request, *args, **kwargs) + return super().get(request, *args, **kwargs) class ForumFavoriteTopics(ListView): @@ -172,15 +173,13 @@ class ForumCreateView(CanCreateMixin, CreateView): template_name = "core/create.jinja" def get_initial(self): - init = super(ForumCreateView, self).get_initial() - try: - parent = Forum.objects.filter(id=self.request.GET["parent"]).first() + init = super().get_initial() + parent = Forum.objects.filter(id=self.request.GET["parent"]).first() + if parent is not None: init["parent"] = parent init["owner_club"] = parent.owner_club init["edit_groups"] = parent.edit_groups.all() init["view_groups"] = parent.view_groups.all() - except: - pass return init @@ -198,7 +197,7 @@ class ForumEditView(CanEditPropMixin, UpdateView): success_url = reverse_lazy("forum:main") def form_valid(self, form): - ret = super(ForumEditView, self).form_valid(form) + ret = super().form_valid(form) if form.cleaned_data["recursive"]: self.object.apply_rights_recursively() return ret @@ -217,7 +216,7 @@ class ForumDetailView(CanViewMixin, DetailView): pk_url_kwarg = "forum_id" def get_context_data(self, **kwargs): - kwargs = super(ForumDetailView, self).get_context_data(**kwargs) + kwargs = super().get_context_data(**kwargs) qs = ( self.object.topics.order_by("-_last_message__date") .select_related("_last_message__author", "author") @@ -254,7 +253,7 @@ class ForumTopicCreateView(CanCreateMixin, CreateView): ) if not request.user.can_view(self.forum): raise PermissionDenied - return super(ForumTopicCreateView, self).dispatch(request, *args, **kwargs) + return super().dispatch(request, *args, **kwargs) def form_valid(self, form): topic = ForumTopic( @@ -263,7 +262,7 @@ class ForumTopicCreateView(CanCreateMixin, CreateView): topic.save() form.instance.topic = topic form.instance.author = self.request.user - return super(ForumTopicCreateView, self).form_valid(form) + return super().form_valid(form) class ForumTopicEditView(CanEditMixin, UpdateView): @@ -300,12 +299,12 @@ class ForumTopicDetailView(CanViewMixin, DetailView): queryset = ForumTopic.objects.select_related("forum__parent") def get_context_data(self, **kwargs): - kwargs = super(ForumTopicDetailView, self).get_context_data(**kwargs) - try: - msg = self.object.get_first_unread_message(self.request.user) + kwargs = super().get_context_data(**kwargs) + msg = self.object.get_first_unread_message(self.request.user) + if msg is None: + kwargs["first_unread_message_id"] = math.inf + else: kwargs["first_unread_message_id"] = msg.id - except: - kwargs["first_unread_message_id"] = float("inf") paginator = Paginator( self.object.messages.select_related("author__avatar_pict") .prefetch_related("topic__forum__edit_groups", "readers") @@ -346,10 +345,10 @@ class ForumMessageEditView(CanEditMixin, UpdateView): ForumMessageMeta( message=self.object, user=self.request.user, action="EDIT" ).save() - return super(ForumMessageEditView, self).form_valid(form) + return super().form_valid(form) def get_context_data(self, **kwargs): - kwargs = super(ForumMessageEditView, self).get_context_data(**kwargs) + kwargs = super().get_context_data(**kwargs) kwargs["topic"] = self.object.topic return kwargs @@ -395,10 +394,10 @@ class ForumMessageCreateView(CanCreateMixin, CreateView): self.topic = get_object_or_404(ForumTopic, id=self.kwargs["topic_id"]) if not request.user.can_view(self.topic): raise PermissionDenied - return super(ForumMessageCreateView, self).dispatch(request, *args, **kwargs) + return super().dispatch(request, *args, **kwargs) def get_initial(self): - init = super(ForumMessageCreateView, self).get_initial() + init = super().get_initial() try: message = ( ForumMessage.objects.select_related("author") @@ -419,9 +418,9 @@ class ForumMessageCreateView(CanCreateMixin, CreateView): def form_valid(self, form): form.instance.topic = self.topic form.instance.author = self.request.user - return super(ForumMessageCreateView, self).form_valid(form) + return super().form_valid(form) def get_context_data(self, **kwargs): - kwargs = super(ForumMessageCreateView, self).get_context_data(**kwargs) + kwargs = super().get_context_data(**kwargs) kwargs["topic"] = self.topic return kwargs diff --git a/galaxy/apps.py b/galaxy/apps.py index d3b3e849..7a1584d2 100644 --- a/galaxy/apps.py +++ b/galaxy/apps.py @@ -1,4 +1,3 @@ -# -*- coding:utf-8 -* # # Copyright 2023 # - Skia diff --git a/galaxy/management/commands/generate_galaxy_test_data.py b/galaxy/management/commands/generate_galaxy_test_data.py index 15cf7f48..25437def 100644 --- a/galaxy/management/commands/generate_galaxy_test_data.py +++ b/galaxy/management/commands/generate_galaxy_test_data.py @@ -1,4 +1,3 @@ -# -*- coding:utf-8 -* # # Copyright 2023 # - Skia @@ -73,7 +72,9 @@ class Command(BaseCommand): def handle(self, *args, **options): self.logger = logging.getLogger("main") if options["verbosity"] < 0 or 2 < options["verbosity"]: - warnings.warn("verbosity level should be between 0 and 2 included") + warnings.warn( + "verbosity level should be between 0 and 2 included", stacklevel=2 + ) if options["verbosity"] == 2: self.logger.setLevel(logging.DEBUG) diff --git a/galaxy/management/commands/rule_galaxy.py b/galaxy/management/commands/rule_galaxy.py index 1743fadc..90510b3f 100644 --- a/galaxy/management/commands/rule_galaxy.py +++ b/galaxy/management/commands/rule_galaxy.py @@ -1,4 +1,3 @@ -# -*- coding:utf-8 -* # # Copyright 2023 # - Skia @@ -42,7 +41,9 @@ class Command(BaseCommand): def handle(self, *args, **options): logger = logging.getLogger("main") if options["verbosity"] < 0 or 2 < options["verbosity"]: - warnings.warn("verbosity level should be between 0 and 2 included") + warnings.warn( + "verbosity level should be between 0 and 2 included", stacklevel=2 + ) if options["verbosity"] == 2: logger.setLevel(logging.DEBUG) diff --git a/galaxy/models.py b/galaxy/models.py index cca7397d..0a4674b0 100644 --- a/galaxy/models.py +++ b/galaxy/models.py @@ -1,4 +1,3 @@ -# -*- coding:utf-8 -* # # Copyright 2023 # - Skia @@ -87,7 +86,7 @@ def current_star(self) -> Optional[GalaxyStar]: # Adding a shortcut to User class for getting its star belonging to the latest ruled Galaxy -setattr(User, "current_star", current_star) +User.current_star = current_star class GalaxyLane(models.Model): @@ -128,6 +127,9 @@ class GalaxyLane(models.Model): default=0, ) + def __str__(self): + return f"{self.star1} -> {self.star2} ({self.distance})" + class StarDict(TypedDict): id: int diff --git a/galaxy/tests.py b/galaxy/tests.py index cfbaf5ca..6eb334ef 100644 --- a/galaxy/tests.py +++ b/galaxy/tests.py @@ -1,4 +1,3 @@ -# -*- coding:utf-8 -* # # Copyright 2023 # - Skia diff --git a/galaxy/urls.py b/galaxy/urls.py index fcab45bc..df8a957a 100644 --- a/galaxy/urls.py +++ b/galaxy/urls.py @@ -1,4 +1,3 @@ -# -*- coding:utf-8 -* # # Copyright 2023 # - Skia diff --git a/galaxy/views.py b/galaxy/views.py index 3e0b33da..fe27f978 100644 --- a/galaxy/views.py +++ b/galaxy/views.py @@ -1,4 +1,3 @@ -# -*- coding:utf-8 -* # # Copyright 2023 # - Skia @@ -44,13 +43,13 @@ class GalaxyUserView(CanViewMixin, UserTabsMixin, DetailView): current_tab = "galaxy" def get_object(self, *args, **kwargs): - user: User = super(GalaxyUserView, self).get_object(*args, **kwargs) + user: User = super().get_object(*args, **kwargs) if user.current_star is None: raise Http404(_("This citizen has not yet joined the galaxy")) return user def get_context_data(self, **kwargs): - kwargs = super(GalaxyUserView, self).get_context_data(**kwargs) + kwargs = super().get_context_data(**kwargs) kwargs["lanes"] = ( GalaxyLane.objects.filter( Q(star1=self.object.current_star) | Q(star2=self.object.current_star) diff --git a/launderette/__init__.py b/launderette/__init__.py index 0aa913c4..a098e7ba 100644 --- a/launderette/__init__.py +++ b/launderette/__init__.py @@ -1,4 +1,3 @@ -# -*- coding:utf-8 -* # # Copyright 2023 © AE UTBM # ae@utbm.fr / ae.info@utbm.fr diff --git a/launderette/admin.py b/launderette/admin.py index a4499d0e..c40a7fd0 100644 --- a/launderette/admin.py +++ b/launderette/admin.py @@ -1,4 +1,3 @@ -# -*- coding:utf-8 -* # # Copyright 2023 © AE UTBM # ae@utbm.fr / ae.info@utbm.fr diff --git a/launderette/migrations/0001_initial.py b/launderette/migrations/0001_initial.py index f1548cd2..2c1d70d1 100644 --- a/launderette/migrations/0001_initial.py +++ b/launderette/migrations/0001_initial.py @@ -1,4 +1,3 @@ -# -*- coding: utf-8 -*- from __future__ import unicode_literals import django.db.models.deletion @@ -177,6 +176,6 @@ class Migration(migrations.Migration): ), ), migrations.AlterUniqueTogether( - name="token", unique_together=set([("name", "launderette", "type")]) + name="token", unique_together={("name", "launderette", "type")} ), ] diff --git a/launderette/models.py b/launderette/models.py index c2f344bb..0abae7ab 100644 --- a/launderette/models.py +++ b/launderette/models.py @@ -1,4 +1,3 @@ -# -*- coding:utf-8 -* # # Copyright 2023 © AE UTBM # ae@utbm.fr / ae.info@utbm.fr @@ -38,6 +37,12 @@ class Launderette(models.Model): class Meta: verbose_name = _("Launderette") + def __str__(self): + return self.name + + def get_absolute_url(self): + return reverse("launderette:launderette_list") + def is_owned_by(self, user): """ Method to see if that object can be edited by the given user @@ -64,12 +69,6 @@ class Launderette(models.Model): def can_be_viewed_by(self, user): return user.is_subscribed - def __str__(self): - return self.name - - def get_absolute_url(self): - return reverse("launderette:launderette_list") - def get_machine_list(self): return Machine.objects.filter(launderette_id=self.id) @@ -99,6 +98,15 @@ class Machine(models.Model): class Meta: verbose_name = _("Machine") + def __str__(self): + return "%s %s" % (self._meta.verbose_name, self.name) + + def get_absolute_url(self): + return reverse( + "launderette:launderette_admin", + kwargs={"launderette_id": self.launderette.id}, + ) + def is_owned_by(self, user): """ Method to see if that object can be edited by the given user @@ -113,15 +121,6 @@ class Machine(models.Model): return True return False - def __str__(self): - return "%s %s" % (self._meta.verbose_name, self.name) - - def get_absolute_url(self): - return reverse( - "launderette:launderette_admin", - kwargs={"launderette_id": self.launderette.id}, - ) - class Token(models.Model): name = models.CharField(_("name"), max_length=5) @@ -149,11 +148,17 @@ class Token(models.Model): unique_together = ("name", "launderette", "type") ordering = ["type", "name"] + def __str__(self): + return ( + f"{self.__class__._meta.verbose_name} {self.get_type_display()} " + f"#{self.name} ({self.launderette.name})" + ) + def save(self, *args, **kwargs): if self.name == "": raise DataError(_("Token name can not be blank")) else: - super(Token, self).save(*args, **kwargs) + super().save(*args, **kwargs) def is_owned_by(self, user): """ @@ -169,18 +174,6 @@ class Token(models.Model): return True return False - def __str__(self): - return ( - self.__class__._meta.verbose_name - + " " - + self.get_type_display() - + " #" - + self.name - + " (" - + self.launderette.name - + ")" - ) - def is_avaliable(self): if not self.borrow_date and not self.user: return True @@ -215,9 +208,6 @@ class Slot(models.Model): verbose_name = _("Slot") ordering = ["start_date"] - def is_owned_by(self, user): - return user == self.user - def __str__(self): return "User: %s - Date: %s - Type: %s - Machine: %s - Token: %s" % ( self.user, @@ -226,3 +216,6 @@ class Slot(models.Model): self.machine.name, self.token, ) + + def is_owned_by(self, user): + return user == self.user diff --git a/launderette/tests.py b/launderette/tests.py index d888e761..48d8f1f6 100644 --- a/launderette/tests.py +++ b/launderette/tests.py @@ -1,4 +1,3 @@ -# -*- coding:utf-8 -* # # Copyright 2023 © AE UTBM # ae@utbm.fr / ae.info@utbm.fr diff --git a/launderette/urls.py b/launderette/urls.py index ac270aec..7b8c4f8b 100644 --- a/launderette/urls.py +++ b/launderette/urls.py @@ -1,4 +1,3 @@ -# -*- coding:utf-8 -* # # Copyright 2023 © AE UTBM # ae@utbm.fr / ae.info@utbm.fr diff --git a/launderette/views.py b/launderette/views.py index c0b16eed..39449160 100644 --- a/launderette/views.py +++ b/launderette/views.py @@ -1,4 +1,3 @@ -# -*- coding:utf-8 -* # # Copyright 2023 © AE UTBM # ae@utbm.fr / ae.info@utbm.fr @@ -45,7 +44,7 @@ class LaunderetteMainView(TemplateView): def get_context_data(self, **kwargs): """Add page to the context""" - kwargs = super(LaunderetteMainView, self).get_context_data(**kwargs) + kwargs = super().get_context_data(**kwargs) kwargs["page"] = Page.objects.filter(name="launderette").first() return kwargs @@ -67,7 +66,7 @@ class LaunderetteBookView(CanViewMixin, DetailView): def get(self, request, *args, **kwargs): self.slot_type = "BOTH" self.machines = {} - return super(LaunderetteBookView, self).get(request, *args, **kwargs) + return super().get(request, *args, **kwargs) def post(self, request, *args, **kwargs): self.slot_type = "BOTH" @@ -114,15 +113,15 @@ class LaunderetteBookView(CanViewMixin, DetailView): machine=self.machines["DRYING"], type="DRYING", ).save() - return super(LaunderetteBookView, self).get(request, *args, **kwargs) + return super().get(request, *args, **kwargs) - def check_slot(self, type, date=None): + def check_slot(self, machine_type, date=None): if date is None: date = self.date - for m in self.object.machines.filter(is_working=True, type=type).all(): + for m in self.object.machines.filter(is_working=True, type=machine_type): slot = Slot.objects.filter(start_date=date, machine=m).first() if slot is None: - self.machines[type] = m + self.machines[machine_type] = m return True return False @@ -135,7 +134,7 @@ class LaunderetteBookView(CanViewMixin, DetailView): def get_context_data(self, **kwargs): """Add page to the context""" - kwargs = super(LaunderetteBookView, self).get_context_data(**kwargs) + kwargs = super().get_context_data(**kwargs) kwargs["planning"] = OrderedDict() kwargs["slot_type"] = self.slot_type start_date = datetime.now().replace( @@ -210,7 +209,7 @@ class LaunderetteCreateView(CanCreateMixin, CreateView): c = Counter(name=form.instance.name, club=club, type="OFFICE") c.save() form.instance.counter = c - return super(LaunderetteCreateView, self).form_valid(form) + return super().form_valid(form) class ManageTokenForm(forms.Form): @@ -285,12 +284,12 @@ class LaunderetteAdminView(CanEditPropMixin, BaseFormView, DetailView): def get(self, request, *args, **kwargs): self.object = self.get_object() - return super(LaunderetteAdminView, self).get(request, *args, **kwargs) + return super().get(request, *args, **kwargs) def post(self, request, *args, **kwargs): self.object = self.get_object() form = self.get_form() - return super(LaunderetteAdminView, self).post(request, *args, **kwargs) + return super().post(request, *args, **kwargs) form.launderette = self.object if form.is_valid(): return self.form_valid(form) @@ -303,15 +302,15 @@ class LaunderetteAdminView(CanEditPropMixin, BaseFormView, DetailView): """ form.process(self.object) if form.is_valid(): - return super(LaunderetteAdminView, self).form_valid(form) + return super().form_valid(form) else: - return super(LaunderetteAdminView, self).form_invalid(form) + return super().form_invalid(form) def get_context_data(self, **kwargs): """ We handle here the login form for the barman """ - kwargs = super(LaunderetteAdminView, self).get_context_data(**kwargs) + kwargs = super().get_context_data(**kwargs) if self.request.method == "GET": kwargs["form"] = self.get_form() return kwargs @@ -324,7 +323,7 @@ class LaunderetteAdminView(CanEditPropMixin, BaseFormView, DetailView): class GetLaunderetteUserForm(GetUserForm): def clean(self): - cleaned_data = super(GetLaunderetteUserForm, self).clean() + cleaned_data = super().clean() sub = cleaned_data["user"] if sub.slots.all().count() <= 0: raise forms.ValidationError(_("User has booked no slot")) @@ -341,24 +340,24 @@ class LaunderetteMainClickView(CanEditMixin, BaseFormView, DetailView): def get(self, request, *args, **kwargs): self.object = self.get_object() - return super(LaunderetteMainClickView, self).get(request, *args, **kwargs) + return super().get(request, *args, **kwargs) def post(self, request, *args, **kwargs): self.object = self.get_object() - return super(LaunderetteMainClickView, self).post(request, *args, **kwargs) + return super().post(request, *args, **kwargs) def form_valid(self, form): """ We handle here the redirection, passing the user id of the asked customer """ self.kwargs["user_id"] = form.cleaned_data["user_id"] - return super(LaunderetteMainClickView, self).form_valid(form) + return super().form_valid(form) def get_context_data(self, **kwargs): """ We handle here the login form for the barman """ - kwargs = super(LaunderetteMainClickView, self).get_context_data(**kwargs) + kwargs = super().get_context_data(**kwargs) kwargs["counter"] = self.object.counter kwargs["form"] = self.get_form() kwargs["barmen"] = [self.request.user] @@ -470,7 +469,7 @@ class LaunderetteClickView(CanEditMixin, DetailView, BaseFormView): self.customer = Customer.objects.filter(user__id=self.kwargs["user_id"]).first() self.subscriber = self.customer.user self.operator = request.user - return super(LaunderetteClickView, self).get(request, *args, **kwargs) + return super().get(request, *args, **kwargs) def post(self, request, *args, **kwargs): """Handle the many possibilities of the post request""" @@ -478,20 +477,20 @@ class LaunderetteClickView(CanEditMixin, DetailView, BaseFormView): self.customer = Customer.objects.filter(user__id=self.kwargs["user_id"]).first() self.subscriber = self.customer.user self.operator = request.user - return super(LaunderetteClickView, self).post(request, *args, **kwargs) + return super().post(request, *args, **kwargs) def form_valid(self, form): """ We handle here the redirection, passing the user id of the asked customer """ self.request.session.update(form.last_basket) - return super(LaunderetteClickView, self).form_valid(form) + return super().form_valid(form) def get_context_data(self, **kwargs): """ We handle here the login form for the barman """ - kwargs = super(LaunderetteClickView, self).get_context_data(**kwargs) + kwargs = super().get_context_data(**kwargs) if "form" not in kwargs.keys(): kwargs["form"] = self.get_form() kwargs["counter"] = self.object.counter @@ -531,7 +530,7 @@ class MachineCreateView(CanCreateMixin, CreateView): template_name = "core/create.jinja" def get_initial(self): - ret = super(MachineCreateView, self).get_initial() + ret = super().get_initial() if "launderette" in self.request.GET.keys(): obj = Launderette.objects.filter( id=int(self.request.GET["launderette"]) diff --git a/manage.py b/manage.py index 068281a9..ead6709b 100755 --- a/manage.py +++ b/manage.py @@ -1,5 +1,4 @@ #!/usr/bin/env python3 -# -*- coding:utf-8 -* # # Copyright 2023 © AE UTBM # ae@utbm.fr / ae.info@utbm.fr diff --git a/matmat/urls.py b/matmat/urls.py index 6e657262..e24d933c 100644 --- a/matmat/urls.py +++ b/matmat/urls.py @@ -1,4 +1,3 @@ -# -*- coding:utf-8 -* # # Copyright 2017 # - Sli diff --git a/matmat/views.py b/matmat/views.py index eb769c62..f8c16a51 100644 --- a/matmat/views.py +++ b/matmat/views.py @@ -1,4 +1,3 @@ -# -*- coding:utf-8 -* # # Copyright 2017 # - Sli @@ -71,7 +70,7 @@ class SearchForm(forms.ModelForm): quick = forms.CharField(label=_("Last/First name or nickname"), max_length=255) def __init__(self, *args, **kwargs): - super(SearchForm, self).__init__(*args, **kwargs) + super().__init__(*args, **kwargs) for key in self.fields.keys(): self.fields[key].required = False @@ -110,14 +109,14 @@ class SearchFormListView(FormerSubscriberMixin, SingleObjectMixin, ListView): self.can_see_hidden = False self.init_query = self.init_query.exclude(is_subscriber_viewable=False) - return super(SearchFormListView, self).dispatch(request, *args, **kwargs) + return super().dispatch(request, *args, **kwargs) def post(self, request, *args, **kwargs): return self.get(request, *args, **kwargs) def get_context_data(self, **kwargs): self.object = None - kwargs = super(SearchFormListView, self).get_context_data(**kwargs) + kwargs = super().get_context_data(**kwargs) kwargs["form"] = self.form_class kwargs["result_exists"] = self.result_exists return kwargs @@ -167,7 +166,7 @@ class SearchFormView(FormerSubscriberMixin, FormView): self.init_query = User.objects kwargs["form"] = self.get_form() kwargs["search_type"] = self.search_type - return super(SearchFormView, self).dispatch(request, *args, **kwargs) + return super().dispatch(request, *args, **kwargs) def get(self, request, *args, **kwargs): view = SearchFormListView.as_view() @@ -206,7 +205,7 @@ class SearchClearFormView(FormerSubscriberMixin, View): """ def dispatch(self, request, *args, **kwargs): - super(SearchClearFormView, self).dispatch(request, *args, **kwargs) + super().dispatch(request, *args, **kwargs) if "matmat_search_form" in request.session.keys(): request.session.pop("matmat_search_form") if "matmat_search_result" in request.session.keys(): diff --git a/pedagogy/__init__.py b/pedagogy/__init__.py index 7ea16950..797a089d 100644 --- a/pedagogy/__init__.py +++ b/pedagogy/__init__.py @@ -1,4 +1,3 @@ -# -*- coding:utf-8 -* # # Copyright 2019 # - Sli diff --git a/pedagogy/admin.py b/pedagogy/admin.py index 0f68234d..82bd2549 100644 --- a/pedagogy/admin.py +++ b/pedagogy/admin.py @@ -1,4 +1,3 @@ -# -*- coding:utf-8 -* # # Copyright 2019 # - Sli diff --git a/pedagogy/forms.py b/pedagogy/forms.py index 28810e64..bfa5780b 100644 --- a/pedagogy/forms.py +++ b/pedagogy/forms.py @@ -1,4 +1,3 @@ -# -*- coding:utf-8 -* # # Copyright 2019 # - Sli @@ -66,7 +65,7 @@ class UVForm(forms.ModelForm): } def __init__(self, author_id, *args, **kwargs): - super(UVForm, self).__init__(*args, **kwargs) + super().__init__(*args, **kwargs) self.fields["author"].queryset = User.objects.filter(id=author_id).all() self.fields["author"].initial = author_id @@ -75,11 +74,11 @@ class StarList(forms.NumberInput): template_name = "pedagogy/starlist.jinja" def __init__(self, nubmer_of_stars=0): - super(StarList, self).__init__(None) + super().__init__(None) self.number_of_stars = nubmer_of_stars def get_context(self, name, value, attrs): - context = super(StarList, self).get_context(name, value, attrs) + context = super().get_context(name, value, attrs) context["number_of_stars"] = range(0, self.number_of_stars) context["translations"] = {"do_not_vote": _("Do not vote")} return context @@ -114,7 +113,7 @@ class UVCommentForm(forms.ModelForm): } def __init__(self, author_id, uv_id, is_creation, *args, **kwargs): - super(UVCommentForm, self).__init__(*args, **kwargs) + super().__init__(*args, **kwargs) self.fields["author"].queryset = User.objects.filter(id=author_id).all() self.fields["author"].initial = author_id self.fields["uv"].queryset = UV.objects.filter(id=uv_id).all() @@ -122,7 +121,7 @@ class UVCommentForm(forms.ModelForm): self.is_creation = is_creation def clean(self): - self.cleaned_data = super(UVCommentForm, self).clean() + self.cleaned_data = super().clean() uv = self.cleaned_data.get("uv") author = self.cleaned_data.get("author") @@ -152,7 +151,7 @@ class UVCommentReportForm(forms.ModelForm): } def __init__(self, reporter_id, comment_id, *args, **kwargs): - super(UVCommentReportForm, self).__init__(*args, **kwargs) + super().__init__(*args, **kwargs) self.fields["reporter"].queryset = User.objects.filter(id=reporter_id).all() self.fields["reporter"].initial = reporter_id self.fields["comment"].queryset = UVComment.objects.filter(id=comment_id).all() diff --git a/pedagogy/migrations/0001_initial.py b/pedagogy/migrations/0001_initial.py index 782e65c4..62f9d5c8 100644 --- a/pedagogy/migrations/0001_initial.py +++ b/pedagogy/migrations/0001_initial.py @@ -1,4 +1,3 @@ -# -*- coding: utf-8 -*- # Generated by Django 1.11.20 on 2019-07-05 14:32 from __future__ import unicode_literals diff --git a/pedagogy/migrations/0002_auto_20190827_2251.py b/pedagogy/migrations/0002_auto_20190827_2251.py index 5ab510df..41babcc1 100644 --- a/pedagogy/migrations/0002_auto_20190827_2251.py +++ b/pedagogy/migrations/0002_auto_20190827_2251.py @@ -1,4 +1,3 @@ -# -*- coding:utf-8 -* # # Copyright 2019 # - Sli diff --git a/pedagogy/models.py b/pedagogy/models.py index 0de5c230..2457970f 100644 --- a/pedagogy/models.py +++ b/pedagogy/models.py @@ -1,4 +1,3 @@ -# -*- coding:utf-8 -* # # Copyright 2019 # - Sli @@ -142,6 +141,12 @@ class UV(models.Model): default=0, ) + def __str__(self): + return self.code + + def get_absolute_url(self): + return reverse("pedagogy:uv_detail", kwargs={"uv_id": self.id}) + def is_owned_by(self, user): """ Can be created by superuser, root or pedagogy admin user @@ -161,9 +166,6 @@ class UV(models.Model): return int(sum(comments.values_list(field, flat=True)) / comments.count()) - def get_absolute_url(self): - return reverse("pedagogy:uv_detail", kwargs={"uv_id": self.id}) - def has_user_already_commented(self, user): """ Help prevent multiples comments from the same user @@ -195,9 +197,6 @@ class UV(models.Model): def grade_work_load_average(self): return self.__grade_average_generic("grade_work_load") - def __str__(self): - return self.code - class UVComment(models.Model): """ @@ -253,6 +252,14 @@ class UVComment(models.Model): ) publish_date = models.DateTimeField(_("publish date"), blank=True) + def __str__(self): + return f"{self.uv} - {self.author}" + + def save(self, *args, **kwargs): + if self.publish_date is None: + self.publish_date = timezone.now() + super().save(*args, **kwargs) + def is_owned_by(self, user): """ Is owned by a pedagogy admin, a superuser or the author himself @@ -266,14 +273,6 @@ class UVComment(models.Model): """ return self.reports.exists() - def __str__(self): - return "%s - %s" % (self.uv, self.author) - - def save(self, *args, **kwargs): - if self.publish_date is None: - self.publish_date = timezone.now() - super(UVComment, self).save(*args, **kwargs) - class UVResult(models.Model): """ @@ -304,6 +303,9 @@ class UVResult(models.Model): validators=[validators.RegexValidator("[AP][0-9]{3}")], ) + def __str__(self): + return f"{self.user.username} ; {self.uv.code} ; {self.grade}" + class UVCommentReport(models.Model): """ @@ -324,6 +326,9 @@ class UVCommentReport(models.Model): ) reason = models.TextField(_("reason")) + def __str__(self): + return f"{self.reporter.username} : {self.reason}" + @cached_property def uv(self): return self.comment.uv diff --git a/pedagogy/search_indexes.py b/pedagogy/search_indexes.py index c6bc74af..775f1037 100644 --- a/pedagogy/search_indexes.py +++ b/pedagogy/search_indexes.py @@ -1,4 +1,3 @@ -# -*- coding:utf-8 -* # # Copyright 2019 # - Sli diff --git a/pedagogy/tests.py b/pedagogy/tests.py index 2c61facf..f630ff15 100644 --- a/pedagogy/tests.py +++ b/pedagogy/tests.py @@ -1,4 +1,3 @@ -# -*- coding:utf-8 -* # # Copyright 2019 # - Sli @@ -984,7 +983,7 @@ class UVCommentReportCreateTest(TestCase): self.comment = UVComment(**comment_kwargs) self.comment.save() - def create_report_test(self, username, success): + def create_report_test(self, username: str, *, success: bool): self.client.login(username=username, password="plop") response = self.client.post( reverse("pedagogy:comment_report", kwargs={"comment_id": self.comment.id}), @@ -1001,16 +1000,16 @@ class UVCommentReportCreateTest(TestCase): self.assertEqual(UVCommentReport.objects.all().exists(), success) def test_create_report_root_success(self): - self.create_report_test("root", True) + self.create_report_test("root", success=True) def test_create_report_pedagogy_admin_success(self): - self.create_report_test("tutu", True) + self.create_report_test("tutu", success=True) def test_create_report_subscriber_success(self): - self.create_report_test("sli", True) + self.create_report_test("sli", success=True) def test_create_report_unsubscribed_fail(self): - self.create_report_test("guy", False) + self.create_report_test("guy", success=False) def test_create_report_anonymous_fail(self): response = self.client.post( @@ -1023,7 +1022,7 @@ class UVCommentReportCreateTest(TestCase): def test_notifications(self): assert not self.tutu.notifications.filter(type="PEDAGOGY_MODERATION").exists() # Create a comment report - self.create_report_test("tutu", True) + self.create_report_test("tutu", success=True) # Check that a notification has been created for pedagogy admins assert self.tutu.notifications.filter(type="PEDAGOGY_MODERATION").exists() @@ -1033,7 +1032,7 @@ class UVCommentReportCreateTest(TestCase): assert notif.user.is_in_group(pk=settings.SITH_GROUP_PEDAGOGY_ADMIN_ID) # Check that notifications are not duplicated if not viewed - self.create_report_test("tutu", True) + self.create_report_test("tutu", success=True) assert self.tutu.notifications.filter(type="PEDAGOGY_MODERATION").count() == 1 # Check that a new notification is created when the old one has been viewed @@ -1041,6 +1040,6 @@ class UVCommentReportCreateTest(TestCase): notif.viewed = True notif.save() - self.create_report_test("tutu", True) + self.create_report_test("tutu", success=True) assert self.tutu.notifications.filter(type="PEDAGOGY_MODERATION").count() == 2 diff --git a/pedagogy/urls.py b/pedagogy/urls.py index 8cfca8d2..b8c3bf21 100644 --- a/pedagogy/urls.py +++ b/pedagogy/urls.py @@ -1,4 +1,3 @@ -# -*- coding:utf-8 -* # # Copyright 2019 # - Sli diff --git a/pedagogy/views.py b/pedagogy/views.py index 89187ca5..9bf602ec 100644 --- a/pedagogy/views.py +++ b/pedagogy/views.py @@ -1,4 +1,3 @@ -# -*- coding:utf-8 -* # # Copyright 2019 # - Sli @@ -73,7 +72,7 @@ class CanCreateUVFunctionMixin(View): """ Pass the function to the template """ - kwargs = super(CanCreateUVFunctionMixin, self).get_context_data(**kwargs) + kwargs = super().get_context_data(**kwargs) kwargs["can_create_uv"] = self.can_create_uv return kwargs @@ -93,7 +92,7 @@ class UVDetailFormView(CanViewMixin, CanCreateUVFunctionMixin, DetailFormView): form_class = UVCommentForm def get_form_kwargs(self): - kwargs = super(UVDetailFormView, self).get_form_kwargs() + kwargs = super().get_form_kwargs() kwargs["author_id"] = self.request.user.id kwargs["uv_id"] = self.get_object().id kwargs["is_creation"] = True @@ -101,7 +100,7 @@ class UVDetailFormView(CanViewMixin, CanCreateUVFunctionMixin, DetailFormView): def form_valid(self, form): form.save() - return super(UVDetailFormView, self).form_valid(form) + return super().form_valid(form) def get_success_url(self): return reverse_lazy( @@ -120,7 +119,7 @@ class UVCommentUpdateView(CanEditPropMixin, UpdateView): template_name = "core/edit.jinja" def get_form_kwargs(self): - kwargs = super(UVCommentUpdateView, self).get_form_kwargs() + kwargs = super().get_form_kwargs() obj = self.get_object() kwargs["author_id"] = obj.author.id kwargs["uv_id"] = obj.uv.id @@ -159,7 +158,7 @@ class UVListView(CanViewMixin, CanCreateUVFunctionMixin, ListView): def get(self, *args, **kwargs): if not self.request.GET.get("json", None): # Return normal full template response - return super(UVListView, self).get(*args, **kwargs) + return super().get(*args, **kwargs) # Return serialized response return HttpResponse( @@ -168,7 +167,7 @@ class UVListView(CanViewMixin, CanCreateUVFunctionMixin, ListView): ) def get_queryset(self): - queryset = super(UVListView, self).get_queryset() + queryset = super().get_queryset() search = self.request.GET.get("search", None) additional_filters = {} @@ -219,16 +218,16 @@ class UVCommentReportCreateView(CanCreateMixin, CreateView): def dispatch(self, request, *args, **kwargs): self.uv_comment = get_object_or_404(UVComment, pk=kwargs["comment_id"]) - return super(UVCommentReportCreateView, self).dispatch(request, *args, **kwargs) + return super().dispatch(request, *args, **kwargs) def get_form_kwargs(self): - kwargs = super(UVCommentReportCreateView, self).get_form_kwargs() + kwargs = super().get_form_kwargs() kwargs["reporter_id"] = self.request.user.id kwargs["comment_id"] = self.uv_comment.id return kwargs def form_valid(self, form): - resp = super(UVCommentReportCreateView, self).form_valid(form) + resp = super().form_valid(form) # Send a message to moderation admins for user in ( @@ -264,7 +263,7 @@ class UVModerationFormView(FormView): def dispatch(self, request, *args, **kwargs): if not request.user.is_owner(UV()): raise PermissionDenied - return super(UVModerationFormView, self).dispatch(request, *args, **kwargs) + return super().dispatch(request, *args, **kwargs) def form_valid(self, form): form_clean = form.clean() @@ -280,7 +279,7 @@ class UVModerationFormView(FormView): except ObjectDoesNotExist: # To avoid errors when two reports points the same comment pass - return super(UVModerationFormView, self).form_valid(form) + return super().form_valid(form) def get_success_url(self): return reverse_lazy("pedagogy:moderation") @@ -296,7 +295,7 @@ class UVCreateView(CanCreateMixin, CreateView): template_name = "pedagogy/uv_edit.jinja" def get_form_kwargs(self): - kwargs = super(UVCreateView, self).get_form_kwargs() + kwargs = super().get_form_kwargs() kwargs["author_id"] = self.request.user.id return kwargs @@ -328,7 +327,7 @@ class UVUpdateView(CanEditPropMixin, UpdateView): template_name = "pedagogy/uv_edit.jinja" def get_form_kwargs(self): - kwargs = super(UVUpdateView, self).get_form_kwargs() + kwargs = super().get_form_kwargs() obj = self.get_object() kwargs["author_id"] = obj.author.id return kwargs diff --git a/pyproject.toml b/pyproject.toml index 2808d848..07f823dd 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -70,7 +70,21 @@ optional = true version = "1.4.25" [tool.ruff.lint] -select = ["I", "F401"] +select = [ + "A", # shadowing of Python builtins + "B", + "C4", # use comprehensions when possible + "I", # isort + "DJ", # django-specific rules, + "F401", # unused import + "FBT", # boolean trap + "UP008", # Use super() instead of super(__class__, self) + "UP009", # utf-8 encoding declaration is unnecessary +] + +ignore = [ + "DJ001", # null=True in CharField/TextField. this one would require a migration +] [tool.pytest.ini_options] DJANGO_SETTINGS_MODULE = "sith.settings" diff --git a/rootplace/__init__.py b/rootplace/__init__.py index 0aa913c4..a098e7ba 100644 --- a/rootplace/__init__.py +++ b/rootplace/__init__.py @@ -1,4 +1,3 @@ -# -*- coding:utf-8 -* # # Copyright 2023 © AE UTBM # ae@utbm.fr / ae.info@utbm.fr diff --git a/rootplace/admin.py b/rootplace/admin.py index 5531f2a2..1a02ff3a 100644 --- a/rootplace/admin.py +++ b/rootplace/admin.py @@ -1,4 +1,3 @@ -# -*- coding:utf-8 -* # # Copyright 2023 © AE UTBM # ae@utbm.fr / ae.info@utbm.fr diff --git a/rootplace/management/__init__.py b/rootplace/management/__init__.py index 6492635a..7419f932 100644 --- a/rootplace/management/__init__.py +++ b/rootplace/management/__init__.py @@ -1,4 +1,3 @@ -# -*- coding:utf-8 -* # # Copyright 2016,2017 # - Sli diff --git a/rootplace/management/commands/__init__.py b/rootplace/management/commands/__init__.py index 6492635a..7419f932 100644 --- a/rootplace/management/commands/__init__.py +++ b/rootplace/management/commands/__init__.py @@ -1,4 +1,3 @@ -# -*- coding:utf-8 -* # # Copyright 2016,2017 # - Sli diff --git a/rootplace/management/commands/delete_all_forum_user_messages.py b/rootplace/management/commands/delete_all_forum_user_messages.py index 5bf9cd4b..90e9433c 100644 --- a/rootplace/management/commands/delete_all_forum_user_messages.py +++ b/rootplace/management/commands/delete_all_forum_user_messages.py @@ -1,5 +1,4 @@ #!/usr/bin/env python3 -# -*- coding:utf-8 -* # # Copyright 2017 # - Sli @@ -55,4 +54,4 @@ class Command(BaseCommand): print("Operation aborted") exit(1) - delete_all_forum_user_messages(user, User.objects.get(id=0), True) + delete_all_forum_user_messages(user, User.objects.get(id=0), verbose=True) diff --git a/rootplace/models.py b/rootplace/models.py index 084dfa73..c6372d7f 100644 --- a/rootplace/models.py +++ b/rootplace/models.py @@ -1,4 +1,3 @@ -# -*- coding:utf-8 -* # # Copyright 2023 © AE UTBM # ae@utbm.fr / ae.info@utbm.fr diff --git a/rootplace/tests.py b/rootplace/tests.py index 5b9e2af1..fb6a7ce6 100644 --- a/rootplace/tests.py +++ b/rootplace/tests.py @@ -1,4 +1,3 @@ -# -*- coding:utf-8 -* # # Copyright 2023 © AE UTBM # ae@utbm.fr / ae.info@utbm.fr diff --git a/rootplace/urls.py b/rootplace/urls.py index 696fb81e..fbf21b97 100644 --- a/rootplace/urls.py +++ b/rootplace/urls.py @@ -1,4 +1,3 @@ -# -*- coding:utf-8 -* # # Copyright 2016,2017 # - Skia diff --git a/rootplace/views.py b/rootplace/views.py index 7a045b73..aae90e77 100644 --- a/rootplace/views.py +++ b/rootplace/views.py @@ -1,4 +1,3 @@ -# -*- coding:utf-8 -* # # Copyright 2016,2017 # - Skia @@ -134,7 +133,7 @@ def merge_users(u1: User, u2: User) -> User: return u1 -def delete_all_forum_user_messages(user, moderator, verbose=False): +def delete_all_forum_user_messages(user, moderator, *, verbose=False): """ Create a ForumMessageMeta that says a forum message is deleted on every forum message of an user @@ -178,7 +177,7 @@ class MergeUsersView(FormView): self.final_user = merge_users( form.cleaned_data["user1"], form.cleaned_data["user2"] ) - return super(MergeUsersView, self).form_valid(form) + return super().form_valid(form) def get_success_url(self): return self.final_user.get_absolute_url() @@ -195,9 +194,7 @@ class DeleteAllForumUserMessagesView(FormView): form_class = SelectUserForm def dispatch(self, request, *args, **kwargs): - res = super(DeleteAllForumUserMessagesView, self).dispatch( - request, *args, **kwargs - ) + res = super().dispatch(request, *args, **kwargs) if request.user.is_root: return res raise PermissionDenied @@ -205,7 +202,7 @@ class DeleteAllForumUserMessagesView(FormView): def form_valid(self, form): self.user = form.cleaned_data["user"] delete_all_forum_user_messages(self.user, self.request.user) - return super(DeleteAllForumUserMessagesView, self).form_valid(form) + return super().form_valid(form) def get_success_url(self): return reverse("core:user_profile", kwargs={"user_id": self.user.id}) diff --git a/sas/__init__.py b/sas/__init__.py index 0aa913c4..a098e7ba 100644 --- a/sas/__init__.py +++ b/sas/__init__.py @@ -1,4 +1,3 @@ -# -*- coding:utf-8 -* # # Copyright 2023 © AE UTBM # ae@utbm.fr / ae.info@utbm.fr diff --git a/sas/admin.py b/sas/admin.py index 3f6c6f42..2ed66e7e 100644 --- a/sas/admin.py +++ b/sas/admin.py @@ -1,4 +1,3 @@ -# -*- coding:utf-8 -* # # Copyright 2023 © AE UTBM # ae@utbm.fr / ae.info@utbm.fr diff --git a/sas/migrations/0001_initial.py b/sas/migrations/0001_initial.py index 7ef55737..55702536 100644 --- a/sas/migrations/0001_initial.py +++ b/sas/migrations/0001_initial.py @@ -1,4 +1,3 @@ -# -*- coding: utf-8 -*- from __future__ import unicode_literals from django.db import migrations diff --git a/sas/migrations/0002_auto_20161119_1241.py b/sas/migrations/0002_auto_20161119_1241.py index 15ba12ad..838bb3ed 100644 --- a/sas/migrations/0002_auto_20161119_1241.py +++ b/sas/migrations/0002_auto_20161119_1241.py @@ -1,4 +1,3 @@ -# -*- coding: utf-8 -*- from __future__ import unicode_literals import django.db.models.deletion @@ -46,6 +45,6 @@ class Migration(migrations.Migration): ], ), migrations.AlterUniqueTogether( - name="peoplepicturerelation", unique_together=set([("user", "picture")]) + name="peoplepicturerelation", unique_together={("user", "picture")} ), ] diff --git a/sas/models.py b/sas/models.py index 3342facf..ee9d5e40 100644 --- a/sas/models.py +++ b/sas/models.py @@ -1,4 +1,3 @@ -# -*- coding:utf-8 -* # # Copyright 2023 © AE UTBM # ae@utbm.fr / ae.info@utbm.fr @@ -31,20 +30,12 @@ from core.utils import exif_auto_rotate, resize_image class SASPictureManager(models.Manager): def get_queryset(self): - return ( - super(SASPictureManager, self) - .get_queryset() - .filter(is_in_sas=True, is_folder=False) - ) + return super().get_queryset().filter(is_in_sas=True, is_folder=False) class SASAlbumManager(models.Manager): def get_queryset(self): - return ( - super(SASAlbumManager, self) - .get_queryset() - .filter(is_in_sas=True, is_folder=True) - ) + return super().get_queryset().filter(is_in_sas=True, is_folder=True) class Picture(SithFile): @@ -97,7 +88,7 @@ class Picture(SithFile): def get_absolute_url(self): return reverse("sas:picture", kwargs={"picture_id": self.id}) - def generate_thumbnails(self, overwrite=False): + def generate_thumbnails(self, *, overwrite=False): im = Image.open(BytesIO(self.file.read())) try: im = exif_auto_rotate(im) diff --git a/sas/tests.py b/sas/tests.py index d888e761..48d8f1f6 100644 --- a/sas/tests.py +++ b/sas/tests.py @@ -1,4 +1,3 @@ -# -*- coding:utf-8 -* # # Copyright 2023 © AE UTBM # ae@utbm.fr / ae.info@utbm.fr diff --git a/sas/urls.py b/sas/urls.py index a425c0e6..af4844d2 100644 --- a/sas/urls.py +++ b/sas/urls.py @@ -1,4 +1,3 @@ -# -*- coding:utf-8 -* # # Copyright 2023 © AE UTBM # ae@utbm.fr / ae.info@utbm.fr diff --git a/sas/views.py b/sas/views.py index c2821bac..367771dc 100644 --- a/sas/views.py +++ b/sas/views.py @@ -1,4 +1,3 @@ -# -*- coding:utf-8 -* # # Copyright 2023 © AE UTBM # ae@utbm.fr / ae.info@utbm.fr @@ -21,7 +20,7 @@ from django.conf import settings from django.core.exceptions import PermissionDenied from django.core.paginator import InvalidPage, Paginator from django.http import Http404, HttpResponse -from django.shortcuts import redirect +from django.shortcuts import get_object_or_404, redirect from django.urls import reverse, reverse_lazy from django.utils.translation import gettext_lazy as _ from django.views.generic import DetailView, TemplateView @@ -43,7 +42,7 @@ class SASForm(forms.Form): required=False, ) - def process(self, parent, owner, files, automodere=False): + def process(self, parent, owner, files, *, automodere=False): try: if self.cleaned_data["album_name"] != "": album = Album( @@ -114,13 +113,13 @@ class SASMainView(FormView): parent=parent, owner=root, files=files, automodere=True ) if self.form.is_valid(): - return super(SASMainView, self).form_valid(self.form) + return super().form_valid(self.form) else: self.form.add_error(None, _("You do not have the permission to do that")) return self.form_invalid(self.form) def get_context_data(self, **kwargs): - kwargs = super(SASMainView, self).get_context_data(**kwargs) + kwargs = super().get_context_data(**kwargs) kwargs["categories"] = Album.objects.filter( parent__id=settings.SITH_SAS_ROOT_DIR_ID ).order_by("id") @@ -140,27 +139,22 @@ class PictureView(CanViewMixin, DetailView, FormMixin): def get(self, request, *args, **kwargs): self.object = self.get_object() self.form = self.get_form() - if "rotate_right" in request.GET.keys(): + if "rotate_right" in request.GET: self.object.rotate(270) - if "rotate_left" in request.GET.keys(): + if "rotate_left" in request.GET: self.object.rotate(90) - if "remove_user" in request.GET.keys(): - try: - user = User.objects.filter(id=int(request.GET["remove_user"])).first() - if user.id == request.user.id or request.user.is_in_group( - pk=settings.SITH_GROUP_SAS_ADMIN_ID - ): - PeoplePictureRelation.objects.filter( - user=user, picture=self.object - ).delete() - except: - pass + if "remove_user" in request.GET: + user = get_object_or_404(User, pk=int(request.GET["remove_user"])) + if user.id == request.user.id or request.user.is_in_group( + pk=settings.SITH_GROUP_SAS_ADMIN_ID + ): + user.picture.filter(picture=self.object).delete() if "ask_removal" in request.GET.keys(): self.object.is_moderated = False self.object.asked_for_removal = True self.object.save() return redirect("sas:album", album_id=self.object.parent.id) - return super(PictureView, self).get(request, *args, **kwargs) + return super().get(request, *args, **kwargs) def post(self, request, *args, **kwargs): self.object = self.get_object() @@ -186,13 +180,13 @@ class PictureView(CanViewMixin, DetailView, FormMixin): url=reverse("core:user_pictures", kwargs={"user_id": u.id}), type="NEW_PICTURES", ).save() - return super(PictureView, self).form_valid(self.form) + return super().form_valid(self.form) else: self.form.add_error(None, _("You do not have the permission to do that")) return self.form_invalid(self.form) def get_context_data(self, **kwargs): - kwargs = super(PictureView, self).get_context_data(**kwargs) + kwargs = super().get_context_data(**kwargs) kwargs["form"] = self.form return kwargs @@ -253,15 +247,15 @@ class AlbumView(CanViewMixin, DetailView, FormMixin): def dispatch(self, request, *args, **kwargs): try: self.asked_page = int(request.GET.get("page", 1)) - except ValueError: - raise Http404 - return super(AlbumView, self).dispatch(request, *args, **kwargs) + except ValueError as e: + raise Http404 from e + return super().dispatch(request, *args, **kwargs) def get(self, request, *args, **kwargs): self.form = self.get_form() if "clipboard" not in request.session.keys(): request.session["clipboard"] = [] - return super(AlbumView, self).get(request, *args, **kwargs) + return super().get(request, *args, **kwargs) def post(self, request, *args, **kwargs): self.object = self.get_object() @@ -285,7 +279,7 @@ class AlbumView(CanViewMixin, DetailView, FormMixin): ), ) if self.form.is_valid(): - return super(AlbumView, self).form_valid(self.form) + return super().form_valid(self.form) else: self.form.add_error(None, _("You do not have the permission to do that")) return self.form_invalid(self.form) @@ -294,14 +288,14 @@ class AlbumView(CanViewMixin, DetailView, FormMixin): return reverse("sas:album", kwargs={"album_id": self.object.id}) def get_context_data(self, **kwargs): - kwargs = super(AlbumView, self).get_context_data(**kwargs) + kwargs = super().get_context_data(**kwargs) kwargs["paginator"] = Paginator( self.object.children_pictures.order_by("id"), self.paginate_by ) try: kwargs["pictures"] = kwargs["paginator"].page(self.asked_page) - except InvalidPage: - raise Http404 + except InvalidPage as e: + raise Http404 from e kwargs["form"] = self.form kwargs["clipboard"] = SithFile.objects.filter( id__in=self.request.session["clipboard"] @@ -317,25 +311,24 @@ class ModerationView(TemplateView): def get(self, request, *args, **kwargs): if request.user.is_in_group(pk=settings.SITH_GROUP_SAS_ADMIN_ID): - return super(ModerationView, self).get(request, *args, **kwargs) + return super().get(request, *args, **kwargs) raise PermissionDenied def post(self, request, *args, **kwargs): + if "album_id" not in request.POST: + raise Http404 if request.user.is_in_group(pk=settings.SITH_GROUP_SAS_ADMIN_ID): - try: - a = Album.objects.filter(id=request.POST["album_id"]).first() - if "moderate" in request.POST.keys(): - a.moderator = request.user - a.is_moderated = True - a.save() - elif "delete" in request.POST.keys(): - a.delete() - except: - pass - return super(ModerationView, self).get(request, *args, **kwargs) + album = get_object_or_404(Album, pk=request.POST["album_id"]) + if "moderate" in request.POST: + album.moderator = request.user + album.is_moderated = True + album.save() + elif "delete" in request.POST: + album.delete() + return super().get(request, *args, **kwargs) def get_context_data(self, **kwargs): - kwargs = super(ModerationView, self).get_context_data(**kwargs) + kwargs = super().get_context_data(**kwargs) kwargs["albums_to_moderate"] = Album.objects.filter( is_moderated=False, is_in_sas=True, is_folder=True ).order_by("id") @@ -381,7 +374,7 @@ class AlbumEditView(CanEditMixin, UpdateView): pk_url_kwarg = "album_id" def form_valid(self, form): - ret = super(AlbumEditView, self).form_valid(form) + ret = super().form_valid(form) if form.cleaned_data["recursive"]: - self.object.apply_rights_recursively(True) + self.object.apply_rights_recursively(only_folders=True) return ret diff --git a/sith/__init__.py b/sith/__init__.py index 0aa913c4..a098e7ba 100644 --- a/sith/__init__.py +++ b/sith/__init__.py @@ -1,4 +1,3 @@ -# -*- coding:utf-8 -* # # Copyright 2023 © AE UTBM # ae@utbm.fr / ae.info@utbm.fr diff --git a/sith/settings.py b/sith/settings.py index b8d0541d..42d7b8d9 100644 --- a/sith/settings.py +++ b/sith/settings.py @@ -1,4 +1,3 @@ -# -*- coding:utf-8 -* # # Copyright 2016,2017 # - Skia diff --git a/sith/toolbar_debug.py b/sith/toolbar_debug.py index 139aec36..ba42955c 100644 --- a/sith/toolbar_debug.py +++ b/sith/toolbar_debug.py @@ -1,4 +1,3 @@ -# -*- coding:utf-8 -* # # Copyright 2016,2017,2021 # - Sli diff --git a/sith/urls.py b/sith/urls.py index 106c2851..087af0c2 100644 --- a/sith/urls.py +++ b/sith/urls.py @@ -1,4 +1,3 @@ -# -*- coding:utf-8 -* # # Copyright 2023 © AE UTBM # ae@utbm.fr / ae.info@utbm.fr diff --git a/sith/wsgi.py b/sith/wsgi.py index 017c575a..de7cdfca 100644 --- a/sith/wsgi.py +++ b/sith/wsgi.py @@ -1,4 +1,3 @@ -# -*- coding:utf-8 -* # # Copyright 2023 © AE UTBM # ae@utbm.fr / ae.info@utbm.fr diff --git a/stock/__init__.py b/stock/__init__.py index 6a83e48e..d728c69f 100644 --- a/stock/__init__.py +++ b/stock/__init__.py @@ -1,4 +1,3 @@ -# -*- coding:utf-8 -* # # Copyright 2016,2017 # - Guillaume "Lo-J" Renaud diff --git a/stock/admin.py b/stock/admin.py index 28985c8c..96bc76ed 100644 --- a/stock/admin.py +++ b/stock/admin.py @@ -1,4 +1,3 @@ -# -*- coding:utf-8 -* # # Copyright 2016,2017 # - Guillaume "Lo-J" Renaud diff --git a/stock/migrations/0001_initial.py b/stock/migrations/0001_initial.py index e203981a..2bd3b142 100644 --- a/stock/migrations/0001_initial.py +++ b/stock/migrations/0001_initial.py @@ -1,4 +1,3 @@ -# -*- coding: utf-8 -*- from __future__ import unicode_literals import django.db.models.deletion diff --git a/stock/models.py b/stock/models.py index f93a1544..89efdad7 100644 --- a/stock/models.py +++ b/stock/models.py @@ -1,4 +1,3 @@ -# -*- coding:utf-8 -* # # Copyright 2016,2017 # - Guillaume "Lo-J" Renaud @@ -150,10 +149,10 @@ class ShoppingListItem(models.Model): ) def __str__(self): - return "%s - %s" % (self.name, self.shopping_lists.first()) - - def can_be_viewed_by(self, user): - return user.is_in_group(pk=settings.SITH_GROUP_COUNTER_ADMIN_ID) + return f"{self.name} - {self.shopping_lists.first()}" def get_absolute_url(self): return reverse("stock:shoppinglist_list") + + def can_be_viewed_by(self, user): + return user.is_in_group(pk=settings.SITH_GROUP_COUNTER_ADMIN_ID) diff --git a/stock/tests.py b/stock/tests.py index 884e1b09..a756580c 100644 --- a/stock/tests.py +++ b/stock/tests.py @@ -1,4 +1,3 @@ -# -*- coding:utf-8 -* # # Copyright 2016,2017 # - Guillaume "Lo-J" Renaud diff --git a/stock/urls.py b/stock/urls.py index cf7ff13f..e6bd54e2 100644 --- a/stock/urls.py +++ b/stock/urls.py @@ -1,4 +1,3 @@ -# -*- coding:utf-8 -* # # Copyright 2016,2017 # - Guillaume "Lo-J" Renaud diff --git a/stock/views.py b/stock/views.py index 72a9ab56..21bd4621 100644 --- a/stock/views.py +++ b/stock/views.py @@ -1,4 +1,3 @@ -# -*- coding:utf-8 -* # # Copyright 2016,2017 # - Guillaume "Lo-J" Renaud @@ -52,7 +51,7 @@ class StockItemList(CounterAdminTabsMixin, CanCreateMixin, ListView): current_tab = "stocks" def get_context_data(self): - ret = super(StockItemList, self).get_context_data() + ret = super().get_context_data() if "stock_id" in self.kwargs.keys(): ret["stock"] = Stock.objects.filter(id=self.kwargs["stock_id"]).first() return ret @@ -78,10 +77,10 @@ class StockEditForm(forms.ModelForm): fields = ["name", "counter"] def __init__(self, *args, **kwargs): - super(StockEditForm, self).__init__(*args, **kwargs) + super().__init__(*args, **kwargs) def save(self, *args, **kwargs): - return super(StockEditForm, self).save(*args, **kwargs) + return super().save(*args, **kwargs) class StockEditView(CounterAdminTabsMixin, CanEditPropMixin, UpdateView): @@ -131,7 +130,7 @@ class StockCreateView(CounterAdminTabsMixin, CanCreateMixin, CreateView): success_url = reverse_lazy("stock:list") def get_initial(self): - ret = super(StockCreateView, self).get_initial() + ret = super().get_initial() if "counter_id" in self.kwargs.keys(): ret["counter"] = self.kwargs["counter_id"] return ret @@ -159,7 +158,7 @@ class StockItemCreateView(CounterAdminTabsMixin, CanCreateMixin, CreateView): current_tab = "stocks" def get_initial(self): - ret = super(StockItemCreateView, self).get_initial() + ret = super().get_initial() if "stock_id" in self.kwargs.keys(): ret["stock_owner"] = self.kwargs["stock_id"] return ret @@ -181,7 +180,7 @@ class StockShoppingListView(CounterAdminTabsMixin, CanViewMixin, ListView): current_tab = "stocks" def get_context_data(self): - ret = super(StockShoppingListView, self).get_context_data() + ret = super().get_context_data() if "stock_id" in self.kwargs.keys(): ret["stock"] = Stock.objects.filter(id=self.kwargs["stock_id"]).first() return ret @@ -271,7 +270,7 @@ class StockItemQuantityBaseFormView( Simple get view """ self.stock = Stock.objects.filter(id=self.kwargs["stock_id"]).first() - return super(StockItemQuantityBaseFormView, self).get(request, *args, **kwargs) + return super().get(request, *args, **kwargs) def post(self, request, *args, **kwargs): """ @@ -279,13 +278,13 @@ class StockItemQuantityBaseFormView( """ self.object = self.get_object() self.stock = Stock.objects.filter(id=self.kwargs["stock_id"]).first() - return super(StockItemQuantityBaseFormView, self).post(request, *args, **kwargs) + return super().post(request, *args, **kwargs) def form_valid(self, form): - return super(StockItemQuantityBaseFormView, self).form_valid(form) + return super().form_valid(form) def get_context_data(self, **kwargs): - kwargs = super(StockItemQuantityBaseFormView, self).get_context_data(**kwargs) + kwargs = super().get_context_data(**kwargs) if "form" not in kwargs.keys(): kwargs["form"] = self.get_form() kwargs["stock"] = self.stock @@ -306,7 +305,7 @@ class StockShoppingListItemListView(CounterAdminTabsMixin, CanViewMixin, ListVie current_tab = "stocks" def get_context_data(self): - ret = super(StockShoppingListItemListView, self).get_context_data() + ret = super().get_context_data() if "shoppinglist_id" in self.kwargs.keys(): ret["shoppinglist"] = ShoppingList.objects.filter( id=self.kwargs["shoppinglist_id"] @@ -451,9 +450,7 @@ class StockUpdateAfterShopppingBaseFormView( self.shoppinglist = ShoppingList.objects.filter( id=self.kwargs["shoppinglist_id"] ).first() - return super(StockUpdateAfterShopppingBaseFormView, self).get( - request, *args, **kwargs - ) + return super().get(request, *args, **kwargs) def post(self, request, *args, **kwargs): """ @@ -463,21 +460,17 @@ class StockUpdateAfterShopppingBaseFormView( self.shoppinglist = ShoppingList.objects.filter( id=self.kwargs["shoppinglist_id"] ).first() - return super(StockUpdateAfterShopppingBaseFormView, self).post( - request, *args, **kwargs - ) + return super().post(request, *args, **kwargs) def form_valid(self, form): """ We handle here the redirection """ - return super(StockUpdateAfterShopppingBaseFormView, self).form_valid(form) + return super().form_valid(form) def get_context_data(self, **kwargs): - kwargs = super(StockUpdateAfterShopppingBaseFormView, self).get_context_data( - **kwargs - ) - if "form" not in kwargs.keys(): + kwargs = super().get_context_data(**kwargs) + if "form" not in kwargs: kwargs["form"] = self.get_form() kwargs["shoppinglist"] = self.shoppinglist kwargs["stock"] = self.shoppinglist.stock_owner @@ -546,7 +539,7 @@ class StockTakeItemsBaseFormView( Simple get view """ self.stock = Stock.objects.filter(id=self.kwargs["stock_id"]).first() - return super(StockTakeItemsBaseFormView, self).get(request, *args, **kwargs) + return super().get(request, *args, **kwargs) def post(self, request, *args, **kwargs): """ @@ -566,13 +559,13 @@ class StockTakeItemsBaseFormView( ) + "?bad_location" ) - return super(StockTakeItemsBaseFormView, self).post(request, *args, **kwargs) + return super().post(request, *args, **kwargs) def form_valid(self, form): - return super(StockTakeItemsBaseFormView, self).form_valid(form) + return super().form_valid(form) def get_context_data(self, **kwargs): - kwargs = super(StockTakeItemsBaseFormView, self).get_context_data(**kwargs) + kwargs = super().get_context_data(**kwargs) if "form" not in kwargs.keys(): kwargs["form"] = self.get_form() kwargs["stock"] = self.stock diff --git a/subscription/__init__.py b/subscription/__init__.py index 0aa913c4..a098e7ba 100644 --- a/subscription/__init__.py +++ b/subscription/__init__.py @@ -1,4 +1,3 @@ -# -*- coding:utf-8 -* # # Copyright 2023 © AE UTBM # ae@utbm.fr / ae.info@utbm.fr diff --git a/subscription/admin.py b/subscription/admin.py index f81e6fde..ad934f98 100644 --- a/subscription/admin.py +++ b/subscription/admin.py @@ -1,4 +1,3 @@ -# -*- coding:utf-8 -* # # Copyright 2023 © AE UTBM # ae@utbm.fr / ae.info@utbm.fr diff --git a/subscription/migrations/0001_initial.py b/subscription/migrations/0001_initial.py index 932fafaf..d47cea7c 100644 --- a/subscription/migrations/0001_initial.py +++ b/subscription/migrations/0001_initial.py @@ -1,4 +1,3 @@ -# -*- coding: utf-8 -*- from __future__ import unicode_literals import django.contrib.auth.models diff --git a/subscription/migrations/0002_auto_20160830_1719.py b/subscription/migrations/0002_auto_20160830_1719.py index db4aae52..9c224b22 100644 --- a/subscription/migrations/0002_auto_20160830_1719.py +++ b/subscription/migrations/0002_auto_20160830_1719.py @@ -1,4 +1,3 @@ -# -*- coding: utf-8 -*- from __future__ import unicode_literals from django.db import migrations, models diff --git a/subscription/migrations/0003_auto_20160902_1914.py b/subscription/migrations/0003_auto_20160902_1914.py index 1cca6149..2f1f127c 100644 --- a/subscription/migrations/0003_auto_20160902_1914.py +++ b/subscription/migrations/0003_auto_20160902_1914.py @@ -1,4 +1,3 @@ -# -*- coding: utf-8 -*- from __future__ import unicode_literals from django.db import migrations, models diff --git a/subscription/migrations/0004_auto_20170821_1849.py b/subscription/migrations/0004_auto_20170821_1849.py index d3a02cc9..f9e09481 100644 --- a/subscription/migrations/0004_auto_20170821_1849.py +++ b/subscription/migrations/0004_auto_20170821_1849.py @@ -1,4 +1,3 @@ -# -*- coding: utf-8 -*- from __future__ import unicode_literals from django.db import migrations, models diff --git a/subscription/migrations/0005_auto_20170821_2054.py b/subscription/migrations/0005_auto_20170821_2054.py index 2e2ee983..ff8b7f65 100644 --- a/subscription/migrations/0005_auto_20170821_2054.py +++ b/subscription/migrations/0005_auto_20170821_2054.py @@ -1,4 +1,3 @@ -# -*- coding: utf-8 -*- from __future__ import unicode_literals from django.db import migrations, models diff --git a/subscription/migrations/0006_auto_20170902_1222.py b/subscription/migrations/0006_auto_20170902_1222.py index 492d47c3..10ceb56f 100644 --- a/subscription/migrations/0006_auto_20170902_1222.py +++ b/subscription/migrations/0006_auto_20170902_1222.py @@ -1,4 +1,3 @@ -# -*- coding: utf-8 -*- from __future__ import unicode_literals from django.db import migrations, models diff --git a/subscription/migrations/0007_auto_20180706_1135.py b/subscription/migrations/0007_auto_20180706_1135.py index 88bbf386..5429f7ac 100644 --- a/subscription/migrations/0007_auto_20180706_1135.py +++ b/subscription/migrations/0007_auto_20180706_1135.py @@ -1,4 +1,3 @@ -# -*- coding: utf-8 -*- # Generated by Django 1.11.13 on 2018-07-06 09:35 from __future__ import unicode_literals diff --git a/subscription/migrations/0008_auto_20180831_2016.py b/subscription/migrations/0008_auto_20180831_2016.py index 35a8f033..92fa517b 100644 --- a/subscription/migrations/0008_auto_20180831_2016.py +++ b/subscription/migrations/0008_auto_20180831_2016.py @@ -1,4 +1,3 @@ -# -*- coding: utf-8 -*- # Generated by Django 1.11.15 on 2018-08-31 18:16 from __future__ import unicode_literals diff --git a/subscription/migrations/0009_auto_20180920_1421.py b/subscription/migrations/0009_auto_20180920_1421.py index 4af79468..13834757 100644 --- a/subscription/migrations/0009_auto_20180920_1421.py +++ b/subscription/migrations/0009_auto_20180920_1421.py @@ -1,4 +1,3 @@ -# -*- coding: utf-8 -*- # Generated by Django 1.11.15 on 2018-09-20 12:21 from __future__ import unicode_literals diff --git a/subscription/migrations/0010_auto_20180920_1441.py b/subscription/migrations/0010_auto_20180920_1441.py index 6d2058c4..4aed82b3 100644 --- a/subscription/migrations/0010_auto_20180920_1441.py +++ b/subscription/migrations/0010_auto_20180920_1441.py @@ -1,4 +1,3 @@ -# -*- coding: utf-8 -*- # Generated by Django 1.11.15 on 2018-09-20 12:41 from __future__ import unicode_literals diff --git a/subscription/migrations/0011_auto_20190825_2215.py b/subscription/migrations/0011_auto_20190825_2215.py index 75fcaa05..fe255336 100644 --- a/subscription/migrations/0011_auto_20190825_2215.py +++ b/subscription/migrations/0011_auto_20190825_2215.py @@ -1,4 +1,3 @@ -# -*- coding: utf-8 -*- # Generated by Django 1.11.20 on 2019-08-25 20:15 from __future__ import unicode_literals diff --git a/subscription/models.py b/subscription/models.py index 5e47ab75..18b3776a 100644 --- a/subscription/models.py +++ b/subscription/models.py @@ -1,4 +1,3 @@ -# -*- coding:utf-8 -* # # Copyright 2023 © AE UTBM # ae@utbm.fr / ae.info@utbm.fr @@ -23,6 +22,7 @@ from django.contrib.auth.forms import PasswordResetForm from django.core.exceptions import ValidationError from django.db import models from django.urls import reverse +from django.utils import timezone from django.utils.translation import gettext_lazy as _ from core.models import User @@ -66,29 +66,14 @@ class Subscription(models.Model): class Meta: ordering = ["subscription_start"] - def clean(self): - try: - for s in ( - Subscription.objects.filter(member=self.member) - .exclude(pk=self.pk) - .all() - ): - if ( - s.is_valid_now() - and s.subscription_end - - timedelta(weeks=settings.SITH_SUBSCRIPTION_END) - > date.today() - ): - raise ValidationError( - _("You can not subscribe many time for the same period") - ) - except: # This should not happen, because the form should have handled the data before, but sadly, it still - # calls the model validation :'( - # TODO see SubscriptionForm's clean method - raise ValidationError(_("Subscription error")) + def __str__(self): + if hasattr(self, "member") and self.member is not None: + return f"{self.member.username} - {self.pk}" + else: + return f"No user - {self.pk}" def save(self, *args, **kwargs): - super(Subscription, self).save() + super().save() from counter.models import Customer _, created = Customer.get_or_create(self.member) @@ -106,11 +91,20 @@ class Subscription(models.Model): def get_absolute_url(self): return reverse("core:user_edit", kwargs={"user_id": self.member.pk}) - def __str__(self): - if hasattr(self, "member") and self.member is not None: - return self.member.username + " - " + str(self.pk) - else: - return "No user - " + str(self.pk) + def clean(self): + today = timezone.now().date() + active_subscriptions = Subscription.objects.exclude(pk=self.pk).filter( + subscription_start__gte=today, subscription_end__lte=today + ) + for s in active_subscriptions: + if ( + s.is_valid_now() + and s.subscription_end - timedelta(weeks=settings.SITH_SUBSCRIPTION_END) + > date.today() + ): + raise ValidationError( + _("You can not subscribe many time for the same period") + ) @staticmethod def compute_start(d: date = None, duration: int = 1, user: User = None) -> date: diff --git a/subscription/tests.py b/subscription/tests.py index c347ab65..6964b4de 100644 --- a/subscription/tests.py +++ b/subscription/tests.py @@ -1,4 +1,3 @@ -# -*- coding:utf-8 -* # # Copyright 2023 © AE UTBM # ae@utbm.fr / ae.info@utbm.fr diff --git a/subscription/urls.py b/subscription/urls.py index 30992187..c8a53949 100644 --- a/subscription/urls.py +++ b/subscription/urls.py @@ -1,4 +1,3 @@ -# -*- coding:utf-8 -* # # Copyright 2023 © AE UTBM # ae@utbm.fr / ae.info@utbm.fr diff --git a/subscription/views.py b/subscription/views.py index ccffd58f..a8bd7177 100644 --- a/subscription/views.py +++ b/subscription/views.py @@ -1,4 +1,3 @@ -# -*- coding:utf-8 -* # # Copyright 2023 © AE UTBM # ae@utbm.fr / ae.info@utbm.fr @@ -31,7 +30,7 @@ from subscription.models import Subscription class SelectionDateForm(forms.Form): def __init__(self, *args, **kwargs): - super(SelectionDateForm, self).__init__(*args, **kwargs) + super().__init__(*args, **kwargs) self.fields["start_date"] = TzAwareDateTimeField( label=_("Start date"), required=True ) @@ -48,7 +47,7 @@ class SubscriptionForm(forms.ModelForm): member = AutoCompleteSelectField("users", required=False, help_text=None) def __init__(self, *args, **kwargs): - super(SubscriptionForm, self).__init__(*args, **kwargs) + super().__init__(*args, **kwargs) # Add fields to allow basic user creation self.fields["last_name"] = forms.CharField( max_length=User._meta.get_field("last_name").max_length @@ -77,7 +76,7 @@ class SubscriptionForm(forms.ModelForm): return subscriber def clean(self): - cleaned_data = super(SubscriptionForm, self).clean() + cleaned_data = super().clean() if ( cleaned_data.get("member") is None and "last_name" not in self.errors.as_data() @@ -125,7 +124,7 @@ class NewSubscription(CreateView): form_class = SubscriptionForm def dispatch(self, request, *arg, **kwargs): - res = super(NewSubscription, self).dispatch(request, *arg, **kwargs) + res = super().dispatch(request, *arg, **kwargs) if request.user.can_create_subscription: return res raise PermissionDenied @@ -152,7 +151,7 @@ class NewSubscription(CreateView): start=form.instance.subscription_start, user=form.instance.member, ) - return super(NewSubscription, self).form_valid(form) + return super().form_valid(form) class SubscriptionsStatsView(FormView): @@ -164,7 +163,7 @@ class SubscriptionsStatsView(FormView): self.start_date = datetime.datetime.today() self.end_date = self.start_date - res = super(SubscriptionsStatsView, self).dispatch(request, *arg, **kwargs) + res = super().dispatch(request, *arg, **kwargs) if request.user.is_root or request.user.is_board_member: return res raise PermissionDenied @@ -173,7 +172,7 @@ class SubscriptionsStatsView(FormView): self.form = self.get_form() self.start_date = self.form["start_date"] self.end_date = self.form["end_date"] - res = super(SubscriptionsStatsView, self).post(request, *args, **kwargs) + res = super().post(request, *args, **kwargs) if request.user.is_root or request.user.is_board_member: return res raise PermissionDenied @@ -188,7 +187,7 @@ class SubscriptionsStatsView(FormView): def get_context_data(self, **kwargs): from subscription.models import Subscription - kwargs = super(SubscriptionsStatsView, self).get_context_data(**kwargs) + kwargs = super().get_context_data(**kwargs) kwargs["subscriptions_total"] = Subscription.objects.filter( subscription_end__gte=self.end_date, subscription_start__lte=self.start_date ) diff --git a/trombi/__init__.py b/trombi/__init__.py index e9ebba43..360a5b0e 100644 --- a/trombi/__init__.py +++ b/trombi/__init__.py @@ -1,4 +1,3 @@ -# -*- coding:utf-8 -* # # Copyright 2017 # - Skia diff --git a/trombi/admin.py b/trombi/admin.py index 0af9bcca..444a42da 100644 --- a/trombi/admin.py +++ b/trombi/admin.py @@ -1,4 +1,3 @@ -# -*- coding:utf-8 -* # # Copyright 2017 # - Skia diff --git a/trombi/migrations/0001_initial.py b/trombi/migrations/0001_initial.py index 3c609c63..e52e4356 100644 --- a/trombi/migrations/0001_initial.py +++ b/trombi/migrations/0001_initial.py @@ -1,4 +1,3 @@ -# -*- coding: utf-8 -*- from __future__ import unicode_literals import datetime diff --git a/trombi/migrations/0002_trombi_show_profiles.py b/trombi/migrations/0002_trombi_show_profiles.py index cb6bdbf5..ff2078c9 100644 --- a/trombi/migrations/0002_trombi_show_profiles.py +++ b/trombi/migrations/0002_trombi_show_profiles.py @@ -1,4 +1,3 @@ -# -*- coding: utf-8 -*- from __future__ import unicode_literals from django.db import migrations, models diff --git a/trombi/migrations/0003_trombicomment_is_moderated.py b/trombi/migrations/0003_trombicomment_is_moderated.py index 47ec61e6..863c602d 100644 --- a/trombi/migrations/0003_trombicomment_is_moderated.py +++ b/trombi/migrations/0003_trombicomment_is_moderated.py @@ -1,4 +1,3 @@ -# -*- coding: utf-8 -*- from __future__ import unicode_literals from django.db import migrations, models diff --git a/trombi/migrations/0004_trombiclubmembership.py b/trombi/migrations/0004_trombiclubmembership.py index eb036839..f7344334 100644 --- a/trombi/migrations/0004_trombiclubmembership.py +++ b/trombi/migrations/0004_trombiclubmembership.py @@ -1,4 +1,3 @@ -# -*- coding: utf-8 -*- from __future__ import unicode_literals import django.db.models.deletion diff --git a/trombi/models.py b/trombi/models.py index b5e7d1a8..c171cf8d 100644 --- a/trombi/models.py +++ b/trombi/models.py @@ -1,4 +1,3 @@ -# -*- coding:utf-8 -* # # Copyright 2017 # - Skia @@ -37,16 +36,12 @@ from core.utils import get_semester_code class TrombiManager(models.Manager): def get_queryset(self): - return super(TrombiManager, self).get_queryset() + return super().get_queryset() class AvailableTrombiManager(models.Manager): def get_queryset(self): - return ( - super(AvailableTrombiManager, self) - .get_queryset() - .filter(subscription_deadline__gte=date.today()) - ) + return super().get_queryset().filter(subscription_deadline__gte=date.today()) class Trombi(models.Model): @@ -88,6 +83,9 @@ class Trombi(models.Model): def __str__(self): return str(self.club.name) + def get_absolute_url(self): + return reverse("trombi:detail", kwargs={"trombi_id": self.id}) + def clean(self): if self.subscription_deadline > self.comments_deadline: raise ValidationError( @@ -97,9 +95,6 @@ class Trombi(models.Model): ) ) - def get_absolute_url(self): - return reverse("trombi:detail", kwargs={"trombi_id": self.id}) - def is_owned_by(self, user): return user.can_edit(self.club) @@ -197,6 +192,9 @@ class TrombiComment(models.Model): content = models.TextField(_("content"), default="") is_moderated = models.BooleanField(_("is the comment moderated"), default=False) + def __str__(self): + return f"{self.author} : {self.content}" + def can_be_viewed_by(self, user): if user.id == self.target.user.id: return False @@ -225,8 +223,8 @@ class TrombiClubMembership(models.Model): def __str__(self): return "%s - %s - %s (%s)" % (self.user, self.club, self.role, self.start) - def can_be_edited_by(self, user): - return user.id == self.user.user.id or user.can_edit(self.user.trombi) - def get_absolute_url(self): return reverse("trombi:profile") + + def can_be_edited_by(self, user): + return user.id == self.user.user.id or user.can_edit(self.user.trombi) diff --git a/trombi/tests.py b/trombi/tests.py index 087c75b4..2eafb036 100644 --- a/trombi/tests.py +++ b/trombi/tests.py @@ -1,4 +1,3 @@ -# -*- coding:utf-8 -* # # Copyright 2017 # - Skia diff --git a/trombi/urls.py b/trombi/urls.py index 49ac42db..1d4cfd5f 100644 --- a/trombi/urls.py +++ b/trombi/urls.py @@ -1,4 +1,3 @@ -# -*- coding:utf-8 -* # # Copyright 2017,2020 # - Skia diff --git a/trombi/views.py b/trombi/views.py index d2bf3231..6392f283 100644 --- a/trombi/views.py +++ b/trombi/views.py @@ -1,4 +1,3 @@ -# -*- coding:utf-8 -* # # Copyright 2017,2020 # - Skia @@ -28,6 +27,7 @@ from datetime import date from ajax_select.fields import AutoCompleteSelectField from django import forms from django.conf import settings +from django.contrib.auth.mixins import LoginRequiredMixin from django.core.exceptions import PermissionDenied from django.forms.models import modelform_factory from django.http import Http404, HttpResponseRedirect @@ -102,7 +102,7 @@ class UserIsInATrombiMixin(View): if not hasattr(self.request.user, "trombi_user"): raise Http404() - return super(UserIsInATrombiMixin, self).dispatch(request, *args, **kwargs) + return super().dispatch(request, *args, **kwargs) class TrombiForm(forms.ModelForm): @@ -148,7 +148,7 @@ class TrombiEditView(CanEditPropMixin, TrombiTabsMixin, UpdateView): current_tab = "admin_tools" def get_success_url(self): - return super(TrombiEditView, self).get_success_url() + "?qn_success" + return super().get_success_url() + "?qn_success" class AddUserForm(forms.Form): @@ -172,10 +172,10 @@ class TrombiDetailView(CanEditMixin, QuickNotifMixin, TrombiTabsMixin, DetailVie self.quick_notif_list.append("qn_success") except: # We don't care about duplicate keys self.quick_notif_list.append("qn_fail") - return super(TrombiDetailView, self).get(request, *args, **kwargs) + return super().get(request, *args, **kwargs) def get_context_data(self, **kwargs): - kwargs = super(TrombiDetailView, self).get_context_data(**kwargs) + kwargs = super().get_context_data(**kwargs) kwargs["form"] = AddUserForm() return kwargs @@ -209,7 +209,7 @@ class TrombiModerateCommentsView( current_tab = "admin_tools" def get_context_data(self, **kwargs): - kwargs = super(TrombiModerateCommentsView, self).get_context_data(**kwargs) + kwargs = super().get_context_data(**kwargs) kwargs["comments"] = TrombiComment.objects.filter( is_moderated=False, author__trombi__id=self.object.id ).exclude(target__user__id=self.request.user.id) @@ -230,7 +230,7 @@ class TrombiModerateCommentView(DetailView): self.object = self.get_object() if not request.user.is_owner(self.object.author.trombi): raise Http404() - return super(TrombiModerateCommentView, self).dispatch(request, *args, **kwargs) + return super().dispatch(request, *args, **kwargs) def post(self, request, *args, **kwargs): if "action" in request.POST: @@ -245,9 +245,7 @@ class TrombiModerateCommentView(DetailView): + "?qn_success" ) elif request.POST["action"] == "reject": - return super(TrombiModerateCommentView, self).get( - request, *args, **kwargs - ) + return super().get(request, *args, **kwargs) elif request.POST["action"] == "delete" and "reason" in request.POST.keys(): self.object.author.user.email_user( subject="[%s] %s" % (settings.SITH_NAME, _("Rejected comment")), @@ -274,7 +272,7 @@ class TrombiModerateCommentView(DetailView): raise Http404 def get_context_data(self, **kwargs): - kwargs = super(TrombiModerateCommentView, self).get_context_data(**kwargs) + kwargs = super().get_context_data(**kwargs) kwargs["form"] = TrombiModerateForm() return kwargs @@ -325,10 +323,10 @@ class UserTrombiToolsView( ) trombi_user.save() self.quick_notif_list += ["qn_success"] - return super(UserTrombiToolsView, self).get(request, *args, **kwargs) + return super().get(request, *args, **kwargs) def get_context_data(self, **kwargs): - kwargs = super(UserTrombiToolsView, self).get_context_data(**kwargs) + kwargs = super().get_context_data(**kwargs) kwargs["user"] = self.request.user if not ( hasattr(self.request.user, "trombi_user") @@ -404,10 +402,7 @@ class UserTrombiDeleteMembershipView(TrombiTabsMixin, CanEditMixin, DeleteView): current_tab = "profile" def get_success_url(self): - return ( - super(UserTrombiDeleteMembershipView, self).get_success_url() - + "?qn_success" - ) + return super().get_success_url() + "?qn_success" # Used by admins when someone does not have every club in his list @@ -423,9 +418,7 @@ class UserTrombiAddMembershipView(TrombiTabsMixin, CreateView): if not self.trombi_user.trombi.is_owned_by(request.user): raise PermissionDenied() - return super(UserTrombiAddMembershipView, self).dispatch( - request, *arg, **kwargs - ) + return super().dispatch(request, *arg, **kwargs) def form_valid(self, form): membership = form.save(commit=False) @@ -447,9 +440,7 @@ class UserTrombiEditMembershipView(CanEditMixin, TrombiTabsMixin, UpdateView): current_tab = "profile" def get_success_url(self): - return ( - super(UserTrombiEditMembershipView, self).get_success_url() + "?qn_success" - ) + return super().get_success_url() + "?qn_success" class UserTrombiProfileView(TrombiTabsMixin, DetailView): @@ -471,10 +462,10 @@ class UserTrombiProfileView(TrombiTabsMixin, DetailView): or not self.object.trombi.show_profiles ): raise Http404() - return super(UserTrombiProfileView, self).get(request, *args, **kwargs) + return super().get(request, *args, **kwargs) -class TrombiCommentFormView(UserIsLoggedMixin): +class TrombiCommentFormView(LoginRequiredMixin, View): """ Create/edit a trombi comment """ @@ -517,7 +508,7 @@ class TrombiCommentFormView(UserIsLoggedMixin): return reverse("trombi:user_tools") + "?qn_success" def get_context_data(self, **kwargs): - kwargs = super(TrombiCommentFormView, self).get_context_data(**kwargs) + kwargs = super().get_context_data(**kwargs) if "user_id" in self.kwargs.keys(): kwargs["target"] = get_object_or_404(TrombiUser, id=self.kwargs["user_id"]) else: @@ -537,7 +528,7 @@ class TrombiCommentCreateView(TrombiCommentFormView, CreateView): old.content = form.instance.content old.save() return HttpResponseRedirect(self.get_success_url()) - return super(TrombiCommentCreateView, self).form_valid(form) + return super().form_valid(form) class TrombiCommentEditView(TrombiCommentFormView, CanViewMixin, UpdateView): @@ -545,4 +536,4 @@ class TrombiCommentEditView(TrombiCommentFormView, CanViewMixin, UpdateView): def form_valid(self, form): form.instance.is_moderated = False - return super(TrombiCommentEditView, self).form_valid(form) + return super().form_valid(form)