From 48d904b6de7ee08873d5e85ac910cc518066da22 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ma=C3=ABl=20Kervella?= Date: Fri, 13 Apr 2018 23:42:22 +0000 Subject: [PATCH] Pep8 compliance on re2o --- preferences/acl.py | 1 + preferences/forms.py | 15 ++- preferences/models.py | 7 +- preferences/urls.py | 2 +- preferences/views.py | 6 +- re2o/__init__.py | 1 - re2o/contributors.py | 27 +++- re2o/field_permissions.py | 5 +- re2o/management/commands/gen_contrib.py | 13 +- re2o/mixins.py | 62 +++++++-- re2o/script_utils.py | 56 ++++---- re2o/settings.py | 2 +- re2o/settings_local.example.py | 17 ++- re2o/templatetags/__init__.py | 1 - re2o/templatetags/acl.py | 134 ++++++++++++-------- re2o/templatetags/massive_bootstrap_form.py | 53 ++------ re2o/templatetags/self_adhesion.py | 1 + re2o/utils.py | 28 ++-- re2o/views.py | 106 +++++++++------- 19 files changed, 313 insertions(+), 224 deletions(-) diff --git a/preferences/acl.py b/preferences/acl.py index 8ffb4c9b..1f3f666e 100644 --- a/preferences/acl.py +++ b/preferences/acl.py @@ -26,6 +26,7 @@ Here are defined some functions to check acl on the application. """ + def can_view(user): """Check if an user can view the application. diff --git a/preferences/forms.py b/preferences/forms.py index a6b8426a..b4a79dd0 100644 --- a/preferences/forms.py +++ b/preferences/forms.py @@ -44,12 +44,16 @@ class EditOptionalUserForm(ModelForm): prefix=prefix, **kwargs ) - self.fields['is_tel_mandatory'].label = 'Exiger un numéro de\ - téléphone' - self.fields['user_solde'].label = 'Activation du solde pour\ - les utilisateurs' + self.fields['is_tel_mandatory'].label = ( + 'Exiger un numéro de téléphone' + ) + self.fields['user_solde'].label = ( + 'Activation du solde pour les utilisateurs' + ) self.fields['max_solde'].label = 'Solde maximum' - self.fields['min_online_payment'].label = 'Montant de rechargement minimum en ligne' + self.fields['min_online_payment'].label = ( + 'Montant de rechargement minimum en ligne' + ) self.fields['self_adhesion'].label = 'Auto inscription' @@ -162,7 +166,6 @@ class EditAssoOptionForm(ModelForm): return cleaned_data - class EditMailMessageOptionForm(ModelForm): """Formulaire d'edition des messages de bienvenue personnalisés""" class Meta: diff --git a/preferences/models.py b/preferences/models.py index c0d761e6..c5363fdd 100644 --- a/preferences/models.py +++ b/preferences/models.py @@ -36,6 +36,7 @@ from django.core.cache import cache from .aes_field import AESEncryptedField from re2o.mixins import AclMixin + class PreferencesModel(models.Model): @classmethod def set_in_cache(cls): @@ -46,7 +47,7 @@ class PreferencesModel(models.Model): @classmethod def get_cached_value(cls, key): instance = cache.get(cls().__class__.__name__.lower()) - if instance == None: + if instance is None: instance = cls.set_in_cache() return getattr(instance, key) @@ -146,7 +147,7 @@ class OptionalMachine(AclMixin, PreferencesModel): @cached_property def ipv6(self): - return not self.get_cached_value('ipv6_mode') == 'DISABLED' + return not self.get_cached_value('ipv6_mode') == 'DISABLED' class Meta: permissions = ( @@ -230,7 +231,7 @@ class GeneralOption(AclMixin, PreferencesModel): blank=True, ) GTU = models.FileField( - upload_to = '', + upload_to='', default="", null=True, blank=True, diff --git a/preferences/urls.py b/preferences/urls.py index 3bc15275..d8aba5b9 100644 --- a/preferences/urls.py +++ b/preferences/urls.py @@ -73,7 +73,7 @@ urlpatterns = [ r'^history/(?P\w+)/(?P[0-9]+)$', re2o.views.history, name='history', - kwargs={'application':'preferences'}, + kwargs={'application': 'preferences'}, ), url(r'^$', views.display_options, name='display-options'), ] diff --git a/preferences/views.py b/preferences/views.py index 22341c28..aa065d1d 100644 --- a/preferences/views.py +++ b/preferences/views.py @@ -128,7 +128,7 @@ def add_service(request): messages.success(request, "Ce service a été ajouté") return redirect(reverse('preferences:display-options')) return form( - {'preferenceform': service, 'action_name' : 'Ajouter'}, + {'preferenceform': service, 'action_name': 'Ajouter'}, 'preferences/preferences.html', request ) @@ -151,7 +151,7 @@ def edit_service(request, service_instance, serviceid): messages.success(request, "Service modifié") return redirect(reverse('preferences:display-options')) return form( - {'preferenceform': service, 'action_name' : 'Editer'}, + {'preferenceform': service, 'action_name': 'Editer'}, 'preferences/preferences.html', request ) @@ -175,7 +175,7 @@ def del_services(request, instances): suivant %s ne peut être supprimé" % services_del) return redirect(reverse('preferences:display-options')) return form( - {'preferenceform': services, 'action_name' : 'Supprimer'}, + {'preferenceform': services, 'action_name': 'Supprimer'}, 'preferences/preferences.html', request ) diff --git a/re2o/__init__.py b/re2o/__init__.py index fc1be5d7..cd256e09 100644 --- a/re2o/__init__.py +++ b/re2o/__init__.py @@ -20,4 +20,3 @@ # You should have received a copy of the GNU General Public License along # with this program; if not, write to the Free Software Foundation, Inc., # 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. - diff --git a/re2o/contributors.py b/re2o/contributors.py index 00e97e41..e5af0a64 100644 --- a/re2o/contributors.py +++ b/re2o/contributors.py @@ -1,3 +1,28 @@ #!/usr/bin/env python3 -CONTRIBUTORS = ['Gabriel "Chirac" Détraz', 'Maël "MoaMoaK" Kervella', 'Hugo "Klafyvel" Levy--Falk', 'Augustin "Dahlaro" Lemesle', 'Goulven "Lhark" Kermarec', 'Guillaume "Guimoz" Goessel', 'Yoann "Nanoy" Pietri', 'Matthieu "Lebanni" Michelet', 'Arthur "Grizzly" Grisel-Davy', 'Simon "Rezatoune" Brélivet', 'Sellem Lev-Arcady', 'David "5-1" Sinquin', 'Pierre "Redstorm" Cadart', 'Éloi "Goslig" Alain', 'Laouen "Volgarr" Fernet', 'Joanne Steiner', '"Krokmou"', 'Thibault "Tipunchetrhum" de Boutray', 'Baptiste "B" Fournier', 'Daniel "Dstan" Stan', 'Hugo "Shaka" Hervieux', '"Mikachu"', 'Thomas "Nymous" Gaudin', '"Esum"'] +CONTRIBUTORS = [ + 'Gabriel "Chirac" Détraz', + 'Maël "MoaMoaK" Kervella', + 'Hugo "Klafyvel" Levy--Falk', + 'Augustin "Dahlaro" Lemesle', + 'Goulven "Lhark" Kermarec', + 'Guillaume "Guimoz" Goessel', + 'Yoann "Nanoy" Pietri', + 'Matthieu "Lebanni" Michelet', + 'Arthur "Grizzly" Grisel-Davy', + 'Simon "Rezatoune" Brélivet', + 'Sellem Lev-Arcady', + 'David "5-1" Sinquin', + 'Pierre "Redstorm" Cadart', + 'Éloi "Goslig" Alain', + 'Laouen "Volgarr" Fernet', + 'Joanne Steiner', + '"Krokmou"', + 'Thibault "Tipunchetrhum" de Boutray', + 'Baptiste "B" Fournier', + 'Daniel "Dstan" Stan', + 'Hugo "Shaka" Hervieux', + '"Mikachu"', + 'Thomas "Nymous" Gaudin', + '"Esum"' +] diff --git a/re2o/field_permissions.py b/re2o/field_permissions.py index dc5466c4..e4c36552 100644 --- a/re2o/field_permissions.py +++ b/re2o/field_permissions.py @@ -43,13 +43,15 @@ class FieldPermissionModelMixin: if result is not None: return result else: - result = user.has_perm(perm) # Don't supply 'obj', or else infinite recursion. + # Don't supply 'obj', or else infinite recursion. + result = user.has_perm(perm) if result: return True # If no requirement can be met, then permission is denied. return False + class FieldPermissionModel(FieldPermissionModelMixin, models.Model): class Meta: abstract = True @@ -76,4 +78,3 @@ class FieldPermissionFormMixin: class FieldPermissionForm(FieldPermissionFormMixin, forms.ModelForm): pass - diff --git a/re2o/management/commands/gen_contrib.py b/re2o/management/commands/gen_contrib.py index 08e57304..06aec202 100644 --- a/re2o/management/commands/gen_contrib.py +++ b/re2o/management/commands/gen_contrib.py @@ -20,18 +20,23 @@ # with this program; if not, write to the Free Software Foundation, Inc., # 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. """ -Write in a python file the list of all contributors sorted by number of commits. -This list is extracted from the FedeRez gitlab repository. +Write in a python file the list of all contributors sorted by number of +commits. This list is extracted from the current gitlab repository. """ from django.core.management.base import BaseCommand, CommandError import os + class Command(BaseCommand): - help = 'Update contributors list' + help = 'Update contributors list' def handle(self, *args, **options): - contributeurs = [item.split('\t')[1] for item in os.popen("git shortlog -s -n").read().split("\n") if '\t' in item] + contributeurs = [ + item.split('\t')[1] + for item in os.popen("git shortlog -s -n").read().split("\n") + if '\t' in item + ] self.stdout.write(self.style.SUCCESS("Exportation Sucessfull")) with open("re2o/contributors.py", "w") as contrib_file: contrib_file.write("#!/usr/bin/env python3\n") diff --git a/re2o/mixins.py b/re2o/mixins.py index 307074ff..48102378 100644 --- a/re2o/mixins.py +++ b/re2o/mixins.py @@ -37,9 +37,15 @@ class RevMixin(object): class FormRevMixin(object): def save(self, *args, **kwargs): if reversion.get_comment() != "" and self.changed_data != []: - reversion.set_comment(reversion.get_comment() + ",%s" % ', '.join(field for field in self.changed_data)) + reversion.set_comment( + reversion.get_comment() + ",%s" + % ', '.join(field for field in self.changed_data) + ) elif self.changed_data: - reversion.set_comment("Champs modifié(s) : %s" % ', '.join(field for field in self.changed_data)) + reversion.set_comment( + "Champs modifié(s) : %s" + % ', '.join(field for field in self.changed_data) + ) return super(FormRevMixin, self).save(*args, **kwargs) @@ -47,12 +53,16 @@ class AclMixin(object): """This mixin is used in nearly every class/models defined in re2o apps. It is used by acl, in models (decorators can_...) and in templates tags :get_instance: Applied on a class, take an id argument, return an instance - :can_create: Applied on a class, take the requested user, return if the user - can do the creation - :can_edit: Applied on an instance, return if the user can edit the instance - :can_delete: Applied on an instance, return if the user can delete the instance - :can_view: Applied on an instance, return if the user can view the instance - :can_view_all: Applied on a class, return if the user can view all instances""" + :can_create: Applied on a class, take the requested user, return if the + user can do the creation + :can_edit: Applied on an instance, return if the user can edit the + instance + :can_delete: Applied on an instance, return if the user can delete the + instance + :can_view: Applied on an instance, return if the user can view the + instance + :can_view_all: Applied on a class, return if the user can view all + instances""" @classmethod def get_classname(cls): @@ -76,8 +86,12 @@ class AclMixin(object): un object :param user_request: instance utilisateur qui fait la requête :return: soit True, soit False avec la raison de l'échec""" - return user_request.has_perm(cls.get_modulename() + '.add_' + cls.get_classname()), u"Vous n'avez pas le droit\ - de créer un " + cls.get_classname() + return ( + user_request.has_perm( + cls.get_modulename() + '.add_' + cls.get_classname() + ), + u"Vous n'avez pas le droit de créer un " + cls.get_classname() + ) def can_edit(self, user_request, *args, **kwargs): """Verifie que l'user a les bons droits pour editer @@ -85,7 +99,12 @@ class AclMixin(object): :param self: Instance à editer :param user_request: Utilisateur qui fait la requête :return: soit True, soit False avec la raison de l'échec""" - return user_request.has_perm(self.get_modulename() + '.change_' + self.get_classname()), u"Vous n'avez pas le droit d'éditer des " + self.get_classname() + return ( + user_request.has_perm( + self.get_modulename() + '.change_' + self.get_classname() + ), + u"Vous n'avez pas le droit d'éditer des " + self.get_classname() + ) def can_delete(self, user_request, *args, **kwargs): """Verifie que l'user a les bons droits pour delete @@ -93,7 +112,12 @@ class AclMixin(object): :param self: Instance à delete :param user_request: Utilisateur qui fait la requête :return: soit True, soit False avec la raison de l'échec""" - return user_request.has_perm(self.get_modulename() + '.delete_' + self.get_classname()), u"Vous n'avez pas le droit d'éditer des " + self.get_classname() + return ( + user_request.has_perm( + self.get_modulename() + '.delete_' + self.get_classname() + ), + u"Vous n'avez pas le droit d'éditer des " + self.get_classname() + ) @classmethod def can_view_all(cls, user_request, *args, **kwargs): @@ -101,7 +125,12 @@ class AclMixin(object): droit particulier view objet correspondant :param user_request: instance user qui fait l'edition :return: True ou False avec la raison de l'échec le cas échéant""" - return user_request.has_perm(cls.get_modulename() + '.view_' + cls.get_classname()), u"Vous n'avez pas le droit de voir des " + cls.get_classname() + return ( + user_request.has_perm( + cls.get_modulename() + '.view_' + cls.get_classname() + ), + u"Vous n'avez pas le droit de voir des " + cls.get_classname() + ) def can_view(self, user_request, *args, **kwargs): """Vérifie qu'on peut bien voir cette instance particulière avec @@ -109,4 +138,9 @@ class AclMixin(object): :param self: instance à voir :param user_request: instance user qui fait l'edition :return: True ou False avec la raison de l'échec le cas échéant""" - return user_request.has_perm(self.get_modulename() + '.view_' + self.get_classname()), u"Vous n'avez pas le droit de voir des " + self.get_classname() + return ( + user_request.has_perm( + self.get_modulename() + '.view_' + self.get_classname() + ), + u"Vous n'avez pas le droit de voir des " + self.get_classname() + ) diff --git a/re2o/script_utils.py b/re2o/script_utils.py index e72ea626..27be81ac 100644 --- a/re2o/script_utils.py +++ b/re2o/script_utils.py @@ -19,15 +19,11 @@ # with this program; if not, write to the Free Software Foundation, Inc., # 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. -import os, sys, pwd +import os +import sys +import pwd -proj_path="/var/www/re2o" -os.environ.setdefault("DJANGO_SETTINGS_MODULE","re2o.settings") -sys.path.append(proj_path) -os.chdir(proj_path) from django.core.wsgi import get_wsgi_application -application = get_wsgi_application() - from django.core.management.base import CommandError from users.models import User @@ -37,14 +33,22 @@ from reversion import revisions as reversion from django.db import transaction from getpass import getpass +proj_path = "/var/www/re2o" +os.environ.setdefault("DJANGO_SETTINGS_MODULE", "re2o.settings") +sys.path.append(proj_path) +os.chdir(proj_path) + +application = get_wsgi_application() + def get_user(pseudo): """Cherche un utilisateur re2o à partir de son pseudo""" user = User.objects.filter(pseudo=pseudo) - if len(user)==0: + if len(user) == 0: raise CommandError("Utilisateur invalide") - if len(user)>1: - raise CommandError("Plusieurs utilisateurs correspondant à ce pseudo. Ceci NE DEVRAIT PAS arriver") + if len(user) > 1: + raise CommandError("Plusieurs utilisateurs correspondant à ce " + "pseudo. Ceci NE DEVRAIT PAS arriver") return user[0] @@ -53,7 +57,7 @@ def get_system_user(): return pwd.getpwuid(int(os.getenv("SUDO_UID") or os.getuid())).pw_name -def form_cli(Form,user,action,*args,**kwargs): +def form_cli(Form, user, action, *args, **kwargs): """ Remplit un formulaire à partir de la ligne de commande Form : le formulaire (sous forme de classe) à remplir @@ -61,26 +65,30 @@ def form_cli(Form,user,action,*args,**kwargs): action : l'action réalisée par le formulaire (pour les logs) Les arguments suivants sont transmis tels quels au formulaire. """ - data={} - dumb_form = Form(user=user,*args,**kwargs) + data = {} + dumb_form = Form(user=user, *args, **kwargs) for key in dumb_form.fields: - if not dumb_form.fields[key].widget.input_type=='hidden': - if dumb_form.fields[key].widget.input_type=='password': - data[key]=getpass("%s : " % dumb_form.fields[key].label) + if not dumb_form.fields[key].widget.input_type == 'hidden': + if dumb_form.fields[key].widget.input_type == 'password': + data[key] = getpass("%s : " % dumb_form.fields[key].label) else: - data[key]=input("%s : " % dumb_form.fields[key].label) + data[key] = input("%s : " % dumb_form.fields[key].label) - form = Form(data,user=user,*args,**kwargs) + form = Form(data, user=user, *args, **kwargs) if not form.is_valid(): sys.stderr.write("Erreurs : \n") for err in form.errors: - #Oui, oui, on gère du HTML là où d'autres ont eu la lumineuse idée de le mettre - sys.stderr.write("\t%s : %s\n" % (err,strip_tags(form.errors[err]))) + # Oui, oui, on gère du HTML là où d'autres ont eu la + # lumineuse idée de le mettre + sys.stderr.write( + "\t%s : %s\n" % (err, strip_tags(form.errors[err])) + ) raise CommandError("Formulaire invalide") with transaction.atomic(), reversion.create_revision(): - form.save() - reversion.set_user(user) - reversion.set_comment(action) + form.save() + reversion.set_user(user) + reversion.set_comment(action) - sys.stdout.write("%s : effectué. La modification peut prendre quelques minutes pour s'appliquer.\n" % action) + sys.stdout.write("%s : effectué. La modification peut prendre " + "quelques minutes pour s'appliquer.\n" % action) diff --git a/re2o/settings.py b/re2o/settings.py index d3c7c725..66149c53 100644 --- a/re2o/settings.py +++ b/re2o/settings.py @@ -126,7 +126,7 @@ LANGUAGE_CODE = 'en' # Proritary location search for translations # then searches in {app}/locale/ for app in INSTALLED_APPS LOCALE_PATHS = [ - BASE_DIR + '/templates/locale/' # to define translations outside of apps + BASE_DIR + '/templates/locale/' # For translations outside of apps ] TIME_ZONE = 'Europe/Paris' diff --git a/re2o/settings_local.example.py b/re2o/settings_local.example.py index c541840f..1418abfa 100644 --- a/re2o/settings_local.example.py +++ b/re2o/settings_local.example.py @@ -73,23 +73,22 @@ EMAIL_PORT = MY_EMAIL_PORT # Reglages pour la bdd ldap LDAP = { - 'base_user_dn' : 'cn=Utilisateurs,dc=example,dc=org', - 'base_userservice_dn' : 'ou=service-users,dc=example,dc=org', - 'base_usergroup_dn' : 'ou=posix,ou=groups,dc=example,dc=org', - 'base_userservicegroup_dn' : 'ou=services,ou=groups,dc=example,dc=org', - 'user_gid' : 500, + 'base_user_dn': 'cn=Utilisateurs,dc=example,dc=org', + 'base_userservice_dn': 'ou=service-users,dc=example,dc=org', + 'base_usergroup_dn': 'ou=posix,ou=groups,dc=example,dc=org', + 'base_userservicegroup_dn': 'ou=services,ou=groups,dc=example,dc=org', + 'user_gid': 500, } UID_RANGES = { - 'users' : [21001,30000], - 'service-users' : [20000,21000], + 'users': [21001, 30000], + 'service-users': [20000, 21000], } # Chaque groupe a un gid assigné, voici la place libre pour assignation GID_RANGES = { - 'posix' : [501, 600], + 'posix': [501, 600], } OPTIONNAL_APPS = () - diff --git a/re2o/templatetags/__init__.py b/re2o/templatetags/__init__.py index 5be3ef33..cff50933 100644 --- a/re2o/templatetags/__init__.py +++ b/re2o/templatetags/__init__.py @@ -18,4 +18,3 @@ # You should have received a copy of the GNU General Public License along # with this program; if not, write to the Free Software Foundation, Inc., # 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. - diff --git a/re2o/templatetags/acl.py b/re2o/templatetags/acl.py index 0f67169f..cb0d5a68 100644 --- a/re2o/templatetags/acl.py +++ b/re2o/templatetags/acl.py @@ -85,32 +85,32 @@ register = template.Library() MODEL_NAME = { # cotisations - 'Facture' : cotisations.models.Facture, - 'Vente' : cotisations.models.Vente, - 'Article' : cotisations.models.Article, - 'Banque' : cotisations.models.Banque, - 'Paiement' : cotisations.models.Paiement, - 'Cotisation' : cotisations.models.Cotisation, + 'Facture': cotisations.models.Facture, + 'Vente': cotisations.models.Vente, + 'Article': cotisations.models.Article, + 'Banque': cotisations.models.Banque, + 'Paiement': cotisations.models.Paiement, + 'Cotisation': cotisations.models.Cotisation, # machines - 'Machine' : machines.models.Machine, - 'MachineType' : machines.models.MachineType, - 'IpType' : machines.models.IpType, - 'Vlan' : machines.models.Vlan, - 'Nas' : machines.models.Nas, - 'SOA' : machines.models.SOA, - 'Extension' : machines.models.Extension, - 'Mx' : machines.models.Mx, - 'Ns' : machines.models.Ns, - 'Txt' : machines.models.Txt, - 'Srv' : machines.models.Srv, - 'Interface' : machines.models.Interface, - 'Domain' : machines.models.Domain, - 'IpList' : machines.models.IpList, - 'Ipv6List' : machines.models.Ipv6List, - 'machines.Service' : machines.models.Service, - 'Service_link' : machines.models.Service_link, - 'OuverturePortList' : machines.models.OuverturePortList, - 'OuverturePort' : machines.models.OuverturePort, + 'Machine': machines.models.Machine, + 'MachineType': machines.models.MachineType, + 'IpType': machines.models.IpType, + 'Vlan': machines.models.Vlan, + 'Nas': machines.models.Nas, + 'SOA': machines.models.SOA, + 'Extension': machines.models.Extension, + 'Mx': machines.models.Mx, + 'Ns': machines.models.Ns, + 'Txt': machines.models.Txt, + 'Srv': machines.models.Srv, + 'Interface': machines.models.Interface, + 'Domain': machines.models.Domain, + 'IpList': machines.models.IpList, + 'Ipv6List': machines.models.Ipv6List, + 'machines.Service': machines.models.Service, + 'Service_link': machines.models.Service_link, + 'OuverturePortList': machines.models.OuverturePortList, + 'OuverturePort': machines.models.OuverturePort, # preferences 'OptionalUser': preferences.models.OptionalUser, 'OptionalMachine': preferences.models.OptionalMachine, @@ -120,25 +120,25 @@ MODEL_NAME = { 'AssoOption': preferences.models.AssoOption, 'MailMessageOption': preferences.models.MailMessageOption, # topologie - 'Stack' : topologie.models.Stack, - 'Switch' : topologie.models.Switch, - 'AccessPoint' : topologie.models.AccessPoint, - 'ModelSwitch' : topologie.models.ModelSwitch, - 'ConstructorSwitch' : topologie.models.ConstructorSwitch, - 'Port' : topologie.models.Port, - 'Room' : topologie.models.Room, - 'Building' : topologie.models.Building, - 'SwitchBay' : topologie.models.SwitchBay, + 'Stack': topologie.models.Stack, + 'Switch': topologie.models.Switch, + 'AccessPoint': topologie.models.AccessPoint, + 'ModelSwitch': topologie.models.ModelSwitch, + 'ConstructorSwitch': topologie.models.ConstructorSwitch, + 'Port': topologie.models.Port, + 'Room': topologie.models.Room, + 'Building': topologie.models.Building, + 'SwitchBay': topologie.models.SwitchBay, # users - 'User' : users.models.User, - 'Adherent' : users.models.Adherent, - 'Club' : users.models.Club, - 'ServiceUser' : users.models.ServiceUser, - 'School' : users.models.School, - 'ListRight' : users.models.ListRight, - 'ListShell' : users.models.ListShell, - 'Ban' : users.models.Ban, - 'Whitelist' : users.models.Whitelist, + 'User': users.models.User, + 'Adherent': users.models.Adherent, + 'Club': users.models.Club, + 'ServiceUser': users.models.ServiceUser, + 'School': users.models.School, + 'ListRight': users.models.ListRight, + 'ListShell': users.models.ListShell, + 'Ban': users.models.Ban, + 'Whitelist': users.models.Whitelist, } @@ -184,17 +184,41 @@ def get_callback(tag_name, obj=None): if tag_name == 'cannot_view_all': return acl_fct(obj.can_view_all, True) if tag_name == 'can_view_app': - return acl_fct(lambda x : (not any(not sys.modules[o].can_view(x) for o in obj), None), False) + return acl_fct( + lambda x: ( + not any(not sys.modules[o].can_view(x) for o in obj), + None + ), + False + ) if tag_name == 'cannot_view_app': - return acl_fct(lambda x : (not any(not sys.modules[o].can_view(x) for o in obj), None), True) + return acl_fct( + lambda x: ( + not any(not sys.modules[o].can_view(x) for o in obj), + None + ), + True + ) if tag_name == 'can_edit_history': - return acl_fct(lambda user:(user.has_perm('admin.change_logentry'),None),False) + return acl_fct( + lambda user: (user.has_perm('admin.change_logentry'), None), + False + ) if tag_name == 'cannot_edit_history': - return acl_fct(lambda user:(user.has_perm('admin.change_logentry'),None),True) + return acl_fct( + lambda user: (user.has_perm('admin.change_logentry'), None), + True + ) if tag_name == 'can_view_any_app': - return acl_fct(lambda x : (any(sys.modules[o].can_view(x) for o in obj), None), False) + return acl_fct( + lambda x: (any(sys.modules[o].can_view(x) for o in obj), None), + False + ) if tag_name == 'cannot_view_any_app': - return acl_fct(lambda x : (any(sys.modules[o].can_view(x) for o in obj), None), True) + return acl_fct( + lambda x: (any(sys.modules[o].can_view(x) for o in obj), None), + True + ) raise template.TemplateSyntaxError( "%r tag is not a valid can_xxx tag" % tag_name @@ -246,11 +270,11 @@ def acl_app_filter(parser, token): tag_name, *app_name = token.split_contents() except ValueError: raise template.TemplateSyntaxError( - "%r tag require 1 argument : an application" + "%r tag require 1 argument: an application" % token.contents.split()[0] ) for name in app_name: - if not name in sys.modules.keys(): + if name not in sys.modules.keys(): raise template.TemplateSyntaxError( "%r is not a registered application for acl." % name @@ -270,6 +294,7 @@ def acl_app_filter(parser, token): return AclNode(callback, oknodes, konodes) + @register.tag('can_change') @register.tag('cannot_change') def acl_change_filter(parser, token): @@ -283,7 +308,7 @@ def acl_change_filter(parser, token): args = tag_content[3:] except ValueError: raise template.TemplateSyntaxError( - "%r tag require at least 2 argument : the model and the field" + "%r tag require at least 2 argument: the model and the field" % token.contents.split()[0] ) @@ -306,6 +331,7 @@ def acl_change_filter(parser, token): return AclNode(callback, oknodes, konodes, *args) + @register.tag('can_create') @register.tag('cannot_create') @register.tag('can_edit_all') @@ -324,7 +350,7 @@ def acl_model_filter(parser, token): args = tag_content[2:] except ValueError: raise template.TemplateSyntaxError( - "%r tag require at least 1 argument : the model" + "%r tag require at least 1 argument: the model" % token.contents.split()[0] ) @@ -364,7 +390,7 @@ def acl_instance_filter(parser, token): args = tag_content[2:] except ValueError: raise template.TemplateSyntaxError( - "%r tag require at least 1 argument : the instance" + "%r tag require at least 1 argument: the instance" % token.contents.split()[0] ) diff --git a/re2o/templatetags/massive_bootstrap_form.py b/re2o/templatetags/massive_bootstrap_form.py index 26a9bcc8..8bfdbee8 100644 --- a/re2o/templatetags/massive_bootstrap_form.py +++ b/re2o/templatetags/massive_bootstrap_form.py @@ -36,13 +36,14 @@ from bootstrap3.forms import render_field register = template.Library() + @register.simple_tag def massive_bootstrap_form(form, mbf_fields, *args, **kwargs): """ Render a form where some specific fields are rendered using Twitter - Typeahead and/or splitree's Bootstrap Tokenfield to improve the performance, the - speed and UX when dealing with very large datasets (select with 50k+ elts - for instance). + Typeahead and/or splitree's Bootstrap Tokenfield to improve the + performance, the speed and UX when dealing with very large datasets + (select with 50k+ elts for instance). When the fields specified should normally be rendered as a select with single selectable option, Twitter Typeahead is used for a better display and the matching query engine. When dealing with multiple selectable @@ -189,8 +190,6 @@ def massive_bootstrap_form(form, mbf_fields, *args, **kwargs): return mbf_form.render() - - class MBFForm(): """ An object to hold all the information and useful methods needed to create and render a massive django form into an actual HTML and JS @@ -198,7 +197,6 @@ class MBFForm(): Every field that is not listed is rendered as a normal bootstrap_field. """ - def __init__(self, form, mbf_fields, *args, **kwargs): # The django form object self.form = form @@ -224,14 +222,13 @@ class MBFForm(): # HTML code to insert inside a template self.html = "" - def render(self): """ HTML code for the fully rendered form with all the necessary form """ for name, field in self.form.fields.items(): - if not name in self.exclude: + if name not in self.exclude: - if name in self.fields and not name in self.hidden_fields: + if name in self.fields and name not in self.hidden_fields: mbf_field = MBFField( name, field, @@ -256,9 +253,6 @@ class MBFForm(): return mark_safe(self.html) - - - class MBFField(): """ An object to hold all the information and useful methods needed to create and render a massive django form field into an actual HTML and JS @@ -270,7 +264,6 @@ class MBFField(): the displayed input. It's used to store the actual data that will be sent to the server """ - def __init__(self, name_, field_, bound_, choices_, engine_, match_func_, update_on_, gen_select_, *args_, **kwargs_): @@ -278,8 +271,8 @@ class MBFField(): if not isinstance(field_.widget, Select): raise ValueError( ('Field named {f_name} is not a Select and' - 'can\'t be rendered with massive_bootstrap_form.' - ).format( + 'can\'t be rendered with massive_bootstrap_form.') + .format( f_name=name_ ) ) @@ -324,7 +317,6 @@ class MBFField(): self.args = args_ self.kwargs = kwargs_ - def default_choices(self): """ JS code of the variable choices_ """ @@ -351,7 +343,6 @@ class MBFField(): ) ) - def default_engine(self): """ Default JS code of the variable engine_ """ return ( @@ -365,7 +356,6 @@ class MBFField(): name=self.name ) - def default_datasets(self): """ Default JS script of the datasets to use with typeahead """ return ( @@ -384,7 +374,6 @@ class MBFField(): match_func=self.match_func ) - def default_match_func(self): """ Default JS code of the matching function to use with typeahed """ return ( @@ -402,14 +391,12 @@ class MBFField(): name=self.name ) - def render(self): """ HTML code for the fully rendered field """ self.gen_displayed_div() self.gen_hidden_div() return mark_safe(self.html) - def gen_displayed_div(self): """ Generate HTML code for the div that contains displayed tags """ if self.gen_select: @@ -434,7 +421,6 @@ class MBFField(): if not self.gen_select: self.html += self.replace_input - def gen_hidden_div(self): """ Generate HTML code for the div that contains hidden tags """ self.gen_full_js() @@ -449,7 +435,6 @@ class MBFField(): attrs={'id': self.div2_id} ) - def hidden_input(self): """ HTML for the hidden input element """ return render_tag( @@ -462,14 +447,12 @@ class MBFField(): } ) - def gen_full_js(self): """ Generate the full script tag containing the JS code """ self.create_js() self.fill_js() self.get_script() - def create_js(self): """ Generate a template for the whole script to use depending on gen_select and multiple """ @@ -549,7 +532,6 @@ class MBFField(): '}} );' ) - def fill_js(self): """ Fill the template with the correct values """ self.js_script = self.js_script.format( @@ -571,11 +553,12 @@ class MBFField(): typ_init_input=self.typeahead_init_input() ) - def get_script(self): """ Insert the JS code inside a script tag """ - self.js_script = render_tag('script', content=mark_safe(self.js_script)) - + self.js_script = render_tag( + 'script', + content=mark_safe(self.js_script) + ) def del_select(self): """ JS code to delete the select if it has been generated and replace @@ -589,7 +572,6 @@ class MBFField(): replace_input=self.replace_input ) - def gen_hidden(self): """ JS code to add a hidden tag to store the value. """ return ( @@ -606,7 +588,6 @@ class MBFField(): html_name=self.bound.html_name ) - def typeahead_init_input(self): """ JS code to init the fields values """ init_key = self.bound.value() or '""' @@ -624,7 +605,6 @@ class MBFField(): hidden_id=self.hidden_id ) - def typeahead_reset_input(self): """ JS code to reset the fields values """ return ( @@ -635,7 +615,6 @@ class MBFField(): hidden_id=self.hidden_id ) - def typeahead_select(self): """ JS code to create the function triggered when an item is selected through typeahead """ @@ -649,7 +628,6 @@ class MBFField(): hidden_id=self.hidden_id ) - def typeahead_change(self): """ JS code of the function triggered when an item is changed (i.e. looses focus and value has changed since the moment it gained focus ) @@ -666,7 +644,6 @@ class MBFField(): hidden_id=self.hidden_id ) - def typeahead_updates(self): """ JS code for binding external fields changes with a reset """ reset_input = self.typeahead_reset_input() @@ -683,7 +660,6 @@ class MBFField(): ) for u_id in self.update_on] return ''.join(updates) - def tokenfield_init_input(self): """ JS code to init the fields values """ init_key = self.bound.value() or '""' @@ -700,7 +676,6 @@ class MBFField(): ) ) - def tokenfield_reset_input(self): """ JS code to reset the fields values """ return ( @@ -709,7 +684,6 @@ class MBFField(): input_id=self.input_id ) - def tokenfield_create(self): """ JS code triggered when a new token is created in tokenfield. """ return ( @@ -739,7 +713,6 @@ class MBFField(): div2_id=self.div2_id ) - def tokenfield_edit(self): """ JS code triggered when a token is edited in tokenfield. """ return ( @@ -765,7 +738,6 @@ class MBFField(): hidden_id=self.hidden_id ) - def tokenfield_remove(self): """ JS code trigggered when a token is removed from tokenfield. """ return ( @@ -791,7 +763,6 @@ class MBFField(): hidden_id=self.hidden_id ) - def tokenfield_updates(self): """ JS code for binding external fields changes with a reset """ reset_input = self.tokenfield_reset_input() diff --git a/re2o/templatetags/self_adhesion.py b/re2o/templatetags/self_adhesion.py index e1577a13..9c749b52 100644 --- a/re2o/templatetags/self_adhesion.py +++ b/re2o/templatetags/self_adhesion.py @@ -24,6 +24,7 @@ from preferences.models import OptionalUser, GeneralOption register = template.Library() + @register.simple_tag def self_adhesion(): options, _created = OptionalUser.objects.get_or_create() diff --git a/re2o/utils.py b/re2o/utils.py index 3bbfffd4..0616bd26 100644 --- a/re2o/utils.py +++ b/re2o/utils.py @@ -118,14 +118,18 @@ def all_has_access(search_time=None): def filter_active_interfaces(interface_set): """Filtre les machines autorisées à sortir sur internet dans une requête""" - return interface_set.filter( - machine__in=Machine.objects.filter( - user__in=all_has_access() - ).filter(active=True) - ).select_related('domain').select_related('machine')\ - .select_related('type').select_related('ipv4')\ - .select_related('domain__extension').select_related('ipv4__ip_type')\ - .distinct() + return (interface_set + .filter( + machine__in=Machine.objects.filter( + user__in=all_has_access() + ).filter(active=True) + ).select_related('domain') + .select_related('machine') + .select_related('type') + .select_related('ipv4') + .select_related('domain__extension') + .select_related('ipv4__ip_type') + .distinct()) def filter_complete_interfaces(interface_set): @@ -160,6 +164,7 @@ def all_active_assigned_interfaces_count(): """ Version light seulement pour compter""" return all_active_interfaces_count().filter(ipv4__isnull=False) + class SortTable: """ Class gathering uselful stuff to sort the colums of a table, according to the column and order requested. It's used with a dict of possible @@ -171,7 +176,8 @@ class SortTable: # the url value and the values are a list of model field name to use to # order the request. They are applied in the order they are given. # A 'default' might be provided to specify what to do if the requested col - # doesn't match any keys. + # doesn't match any keys. + USERS_INDEX = { 'user_name': ['name'], 'user_surname': ['surname'], @@ -255,7 +261,7 @@ class SortTable: } TOPOLOGIE_INDEX_MODEL_SWITCH = { 'model-switch_name': ['reference'], - 'model-switch_contructor' : ['constructor__name'], + 'model-switch_contructor': ['constructor__name'], 'default': ['reference'], } TOPOLOGIE_INDEX_SWITCH_BAY = { @@ -290,6 +296,7 @@ class SortTable: else: return request + def re2o_paginator(request, query_set, pagination_number): """Paginator script for list display in re2o. :request: @@ -307,6 +314,7 @@ def re2o_paginator(request, query_set, pagination_number): results = paginator.page(paginator.num_pages) return results + def remove_user_room(room): """ Déménage de force l'ancien locataire de la chambre """ try: diff --git a/re2o/views.py b/re2o/views.py index 4d7e47d0..f1729fb4 100644 --- a/re2o/views.py +++ b/re2o/views.py @@ -44,12 +44,17 @@ from itertools import chain from preferences.models import Service from preferences.models import OptionalUser, GeneralOption, AssoOption -import users, preferences, cotisations, topologie, machines +import users +import preferences +import cotisations +import topologie +import machines from .utils import re2o_paginator from .settings import BASE_DIR, INSTALLED_APPS, MIDDLEWARE_CLASSES from .contributors import CONTRIBUTORS + def form(ctx, template, request): """Form générique, raccourci importé par les fonctions views du site""" context = ctx @@ -64,56 +69,58 @@ def index(request): services[indice % 3].append(serv) return form({'services_urls': services}, 're2o/index.html', request) + #: Binding the corresponding char sequence of history url to re2o models. HISTORY_BIND = { - 'users' : { - 'user' : users.models.User, - 'ban' : users.models.Ban, - 'whitelist' : users.models.Whitelist, - 'school' : users.models.School, - 'listright' : users.models.ListRight, - 'serviceuser' : users.models.ServiceUser, - 'listshell' : users.models.ListShell, + 'users': { + 'user': users.models.User, + 'ban': users.models.Ban, + 'whitelist': users.models.Whitelist, + 'school': users.models.School, + 'listright': users.models.ListRight, + 'serviceuser': users.models.ServiceUser, + 'listshell': users.models.ListShell, }, - 'preferences' : { - 'service' : preferences.models.Service, + 'preferences': { + 'service': preferences.models.Service, }, - 'cotisations' : { - 'facture' : cotisations.models.Facture, - 'article' : cotisations.models.Article, - 'paiement' : cotisations.models.Paiement, - 'banque' : cotisations.models.Banque, + 'cotisations': { + 'facture': cotisations.models.Facture, + 'article': cotisations.models.Article, + 'paiement': cotisations.models.Paiement, + 'banque': cotisations.models.Banque, }, - 'topologie' : { - 'switch' : topologie.models.Switch, - 'port' : topologie.models.Port, - 'room' : topologie.models.Room, - 'stack' : topologie.models.Stack, - 'modelswitch' : topologie.models.ModelSwitch, - 'constructorswitch' : topologie.models.ConstructorSwitch, - 'accesspoint' : topologie.models.AccessPoint, - 'switchbay' : topologie.models.SwitchBay, - 'building' : topologie.models.Building, + 'topologie': { + 'switch': topologie.models.Switch, + 'port': topologie.models.Port, + 'room': topologie.models.Room, + 'stack': topologie.models.Stack, + 'modelswitch': topologie.models.ModelSwitch, + 'constructorswitch': topologie.models.ConstructorSwitch, + 'accesspoint': topologie.models.AccessPoint, + 'switchbay': topologie.models.SwitchBay, + 'building': topologie.models.Building, }, - 'machines' : { - 'machine' : machines.models.Machine, - 'interface' : machines.models.Interface, - 'domain' : machines.models.Domain, - 'machinetype' : machines.models.MachineType, - 'iptype' : machines.models.IpType, - 'extension' : machines.models.Extension, - 'soa' : machines.models.SOA, - 'mx' : machines.models.Mx, - 'txt' : machines.models.Txt, - 'srv' : machines.models.Srv, - 'ns' : machines.models.Ns, - 'service' : machines.models.Service, - 'vlan' : machines.models.Vlan, - 'nas' : machines.models.Nas, - 'ipv6list' : machines.models.Ipv6List, + 'machines': { + 'machine': machines.models.Machine, + 'interface': machines.models.Interface, + 'domain': machines.models.Domain, + 'machinetype': machines.models.MachineType, + 'iptype': machines.models.IpType, + 'extension': machines.models.Extension, + 'soa': machines.models.SOA, + 'mx': machines.models.Mx, + 'txt': machines.models.Txt, + 'srv': machines.models.Srv, + 'ns': machines.models.Ns, + 'service': machines.models.Service, + 'vlan': machines.models.Vlan, + 'nas': machines.models.Nas, + 'ipv6list': machines.models.Ipv6List, }, } + @login_required def history(request, application, object_name, object_id): """Render history for a model. @@ -144,21 +151,23 @@ def history(request, application, object_name, object_id): instance = model.get_instance(**kwargs) except model.DoesNotExist: messages.error(request, u"Entrée inexistante") - return redirect(reverse('users:profil', - kwargs={'userid':str(request.user.id)} + return redirect(reverse( + 'users:profil', + kwargs={'userid': str(request.user.id)} )) can, msg = instance.can_view(request.user) if not can: messages.error(request, msg or "Vous ne pouvez pas accéder à ce menu") return redirect(reverse( 'users:profil', - kwargs={'userid':str(request.user.id)} + kwargs={'userid': str(request.user.id)} )) pagination_number = GeneralOption.get_cached_value('pagination_number') reversions = Version.objects.get_for_object(instance) if hasattr(instance, 'linked_objects'): for related_object in chain(instance.linked_objects()): - reversions = reversions | Version.objects.get_for_object(related_object) + reversions = (reversions | + Version.objects.get_for_object(related_object)) reversions = re2o_paginator(request, reversions, pagination_number) return render( request, @@ -191,8 +200,8 @@ def about_page(request): request, "re2o/about.html", { - 'description': option.description , - 'AssoName' : option.name , + 'description': option.description, + 'AssoName': option.name, 'git_info_contributors': git_info_contributors, 'git_info_remote': git_info_remote, 'git_info_branch': git_info_branch, @@ -201,4 +210,3 @@ def about_page(request): 'dependencies': dependencies } ) -