From ffebd8fe7a29c0f0a3b6c56dd4aa76ff81421871 Mon Sep 17 00:00:00 2001 From: Jacobe2169 Date: Fri, 26 Jan 2024 13:40:12 +0100 Subject: [PATCH 1/2] add lint ci + lint to black 24 --- .github/workflows/lint.yml | 13 ++ app/api/route_register.py | 1 + app/bib_organismes/forms.py | 40 ++++-- app/env.py | 2 +- app/genericRepository.py | 6 - app/groupe/forms.py | 17 ++- app/liste/forms.py | 14 +- app/migrations/env.py | 22 +-- ...ec215fe023e_upgrade_utilisateurs_schema.py | 9 +- .../versions/9445a69f2bed_usershub.py | 27 ++-- .../versions/f63a8f44c969_usershub_samples.py | 21 +-- app/models.py | 17 +-- app/t_profils/forms.py | 14 +- app/t_roles/forms.py | 64 +++++---- app/t_roles/route.py | 7 +- app/utils/utilssqlalchemy.py | 134 ++++++++---------- 16 files changed, 223 insertions(+), 185 deletions(-) create mode 100644 .github/workflows/lint.yml diff --git a/.github/workflows/lint.yml b/.github/workflows/lint.yml new file mode 100644 index 00000000..20c6ab4d --- /dev/null +++ b/.github/workflows/lint.yml @@ -0,0 +1,13 @@ +name: Lint + +on: [push, pull_request] + +jobs: + backend: + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v3 + with: + fetch-depth: 0 + - name: Backend code formatting check (Black) + uses: psf/black@stable diff --git a/app/api/route_register.py b/app/api/route_register.py index f04cbff7..15c3d71e 100644 --- a/app/api/route_register.py +++ b/app/api/route_register.py @@ -1,6 +1,7 @@ """ Route permettant de manipuler les données de UsersHub via une API """ + from datetime import datetime, timedelta import hashlib diff --git a/app/bib_organismes/forms.py b/app/bib_organismes/forms.py index cfc2609d..702761cf 100644 --- a/app/bib_organismes/forms.py +++ b/app/bib_organismes/forms.py @@ -1,25 +1,37 @@ from flask_wtf import FlaskForm -from wtforms import (StringField, PasswordField, BooleanField, - SubmitField, HiddenField, SelectField, validators +from wtforms import ( + StringField, + PasswordField, + BooleanField, + SubmitField, + HiddenField, + SelectField, + validators, ) from wtforms.validators import DataRequired, Email -# from wtforms_components import IntergerField - +# from wtforms_components import IntergerField class Organisme(FlaskForm): """ Classe du formulaire des Organismes """ - nom_organisme = StringField("Nom de l'organisme", validators=[DataRequired(message="Le nom de l'organisme est obligatoire")]) - adresse_organisme = StringField('Adresse') - cp_organisme = StringField('Code Postal') - ville_organisme = StringField ('Ville') - tel_organisme = StringField('Téléphone') - fax_organisme = StringField('Fax') - email_organisme = StringField('E-mail', validators=[validators.Optional(), Email(message="L'email est incorect")]) + + nom_organisme = StringField( + "Nom de l'organisme", + validators=[DataRequired(message="Le nom de l'organisme est obligatoire")], + ) + adresse_organisme = StringField("Adresse") + cp_organisme = StringField("Code Postal") + ville_organisme = StringField("Ville") + tel_organisme = StringField("Téléphone") + fax_organisme = StringField("Fax") + email_organisme = StringField( + "E-mail", + validators=[validators.Optional(), Email(message="L'email est incorect")], + ) url_organisme = StringField("URL du site web de l'organisme") - url_logo = StringField('Logo (URL)') - id_organisme = HiddenField('id') - submit = SubmitField('Enregistrer') + url_logo = StringField("Logo (URL)") + id_organisme = HiddenField("id") + submit = SubmitField("Enregistrer") diff --git a/app/env.py b/app/env.py index 2fe448c8..b639f044 100644 --- a/app/env.py +++ b/app/env.py @@ -6,5 +6,5 @@ Création de la base avec sqlalchemy """ -os.environ['FLASK_SQLALCHEMY_DB'] = 'app.env.db' +os.environ["FLASK_SQLALCHEMY_DB"] = "app.env.db" db = SQLAlchemy() diff --git a/app/genericRepository.py b/app/genericRepository.py index ab59e607..c931f0c0 100644 --- a/app/genericRepository.py +++ b/app/genericRepository.py @@ -36,7 +36,6 @@ def get_all( order_by=None, order="asc", ): - """ Methode qui retourne un dictionnaire de tout les éléments d'un Model Avec pour paramètres: @@ -65,7 +64,6 @@ def get_all( @classmethod def post(cls, entity_dict): - """ Methode qui ajoute un élément à une table Avec pour paramètres un dictionnaire de cet élément @@ -83,7 +81,6 @@ def post(cls, entity_dict): @classmethod def update(cls, entity_dict): - """ Methode qui met à jour un élément Avec pour paramètre un dictionnaire de cet élément @@ -101,7 +98,6 @@ def update(cls, entity_dict): @classmethod def delete(cls, id): - """ Methode qui supprime un élement d'une table à partir d'un id donné Avec pour paramètre un id (clé primaire) @@ -115,7 +111,6 @@ def delete(cls, id): @classmethod def choixSelect(cls, id, nom, aucun=None, order_by=None): - """ Methode qui retourne un tableau de tuples d'id et de nom Avec pour paramètres un id et un nom @@ -135,4 +130,3 @@ def choixSelect(cls, id, nom, aucun=None, order_by=None): # for col in cls.__table__.columns.keys() # return cls.__table__.columns.keys() - diff --git a/app/groupe/forms.py b/app/groupe/forms.py index 574fd9e2..ccbba84f 100644 --- a/app/groupe/forms.py +++ b/app/groupe/forms.py @@ -4,12 +4,17 @@ class Group(FlaskForm): - """ Classe du formulaire des Groupes """ - nom_role = StringField("Nom", validators=[DataRequired(message='Le nom du group est obligatoire')]) - desc_role = TextAreaField('Description') - groupe = BooleanField('groupe', validators=[DataRequired(message="L'information 'groupe' est obligatoire")]) - id_role = HiddenField('id') - submit = SubmitField('Enregistrer') \ No newline at end of file + + nom_role = StringField( + "Nom", validators=[DataRequired(message="Le nom du group est obligatoire")] + ) + desc_role = TextAreaField("Description") + groupe = BooleanField( + "groupe", + validators=[DataRequired(message="L'information 'groupe' est obligatoire")], + ) + id_role = HiddenField("id") + submit = SubmitField("Enregistrer") diff --git a/app/liste/forms.py b/app/liste/forms.py index a5cb6e35..8e5cc983 100644 --- a/app/liste/forms.py +++ b/app/liste/forms.py @@ -8,8 +8,12 @@ class List(FlaskForm): Classe du formulaire des listes """ - nom_liste = StringField("Nom", validators = [DataRequired(message = 'Le nom de la liste est obligatoire')]) - code_liste = StringField("Code", validators = [DataRequired(message = 'Le code de la liste est obligatoire')]) - desc_liste = TextAreaField('Description') - id_liste = HiddenField('Id') - submit = SubmitField('Enregistrer') \ No newline at end of file + nom_liste = StringField( + "Nom", validators=[DataRequired(message="Le nom de la liste est obligatoire")] + ) + code_liste = StringField( + "Code", validators=[DataRequired(message="Le code de la liste est obligatoire")] + ) + desc_liste = TextAreaField("Description") + id_liste = HiddenField("Id") + submit = SubmitField("Enregistrer") diff --git a/app/migrations/env.py b/app/migrations/env.py index 94521792..b896f2ca 100644 --- a/app/migrations/env.py +++ b/app/migrations/env.py @@ -15,17 +15,19 @@ # Interpret the config file for Python logging. # This line sets up loggers basically. fileConfig(config.config_file_name) -logger = logging.getLogger('alembic.env') +logger = logging.getLogger("alembic.env") # add your model's MetaData object here # for 'autogenerate' support # from myapp import mymodel # target_metadata = mymodel.Base.metadata from flask import current_app + config.set_main_option( - 'sqlalchemy.url', - str(current_app.extensions['migrate'].db.engine.url).replace('%', '%%')) -target_metadata = current_app.extensions['migrate'].db.metadata + "sqlalchemy.url", + str(current_app.extensions["migrate"].db.engine.url).replace("%", "%%"), +) +target_metadata = current_app.extensions["migrate"].db.metadata # other values from the config, defined by the needs of env.py, # can be acquired: @@ -46,9 +48,7 @@ def run_migrations_offline(): """ url = config.get_main_option("sqlalchemy.url") - context.configure( - url=url, target_metadata=target_metadata, literal_binds=True - ) + context.configure(url=url, target_metadata=target_metadata, literal_binds=True) with context.begin_transaction(): context.run_migrations() @@ -66,15 +66,15 @@ def run_migrations_online(): # when there are no changes to the schema # reference: http://alembic.zzzcomputing.com/en/latest/cookbook.html def process_revision_directives(context, revision, directives): - if getattr(config.cmd_opts, 'autogenerate', False): + if getattr(config.cmd_opts, "autogenerate", False): script = directives[0] if script.upgrade_ops.is_empty(): directives[:] = [] - logger.info('No changes in schema detected.') + logger.info("No changes in schema detected.") connectable = engine_from_config( config.get_section(config.config_ini_section), - prefix='sqlalchemy.', + prefix="sqlalchemy.", poolclass=pool.NullPool, ) @@ -83,7 +83,7 @@ def process_revision_directives(context, revision, directives): connection=connection, target_metadata=target_metadata, process_revision_directives=process_revision_directives, - **current_app.extensions['migrate'].configure_args + **current_app.extensions["migrate"].configure_args ) with context.begin_transaction(): diff --git a/app/migrations/versions/6ec215fe023e_upgrade_utilisateurs_schema.py b/app/migrations/versions/6ec215fe023e_upgrade_utilisateurs_schema.py index 9ceb8895..a36642be 100644 --- a/app/migrations/versions/6ec215fe023e_upgrade_utilisateurs_schema.py +++ b/app/migrations/versions/6ec215fe023e_upgrade_utilisateurs_schema.py @@ -5,17 +5,16 @@ Create Date: 2021-09-30 16:29:25.531376 """ + from alembic import op import sqlalchemy as sa # revision identifiers, used by Alembic. -revision = '6ec215fe023e' -down_revision = '9445a69f2bed' +revision = "6ec215fe023e" +down_revision = "9445a69f2bed" branch_labels = None -depends_on = ( - '951b8270a1cf', # utilisateurs -) +depends_on = ("951b8270a1cf",) # utilisateurs def upgrade(): diff --git a/app/migrations/versions/9445a69f2bed_usershub.py b/app/migrations/versions/9445a69f2bed_usershub.py index 278c62c8..73aa9e11 100644 --- a/app/migrations/versions/9445a69f2bed_usershub.py +++ b/app/migrations/versions/9445a69f2bed_usershub.py @@ -4,21 +4,21 @@ Create Date: 2021-08-30 16:33:42.410504 """ + from alembic import op import sqlalchemy as sa # revision identifiers, used by Alembic. -revision = '9445a69f2bed' +revision = "9445a69f2bed" down_revision = None -branch_labels = ('usershub',) -depends_on = ( - 'fa35dfe5ff27', # schema utilisateurs -) +branch_labels = ("usershub",) +depends_on = ("fa35dfe5ff27",) # schema utilisateurs def upgrade(): - op.execute(""" + op.execute( + """ INSERT INTO utilisateurs.t_applications ( code_application, nom_application, @@ -29,8 +29,10 @@ def upgrade(): 'UsersHub', 'Application permettant d''administrer la présente base de données.', NULL) - """) - op.execute(""" + """ + ) + op.execute( + """ INSERT INTO utilisateurs.cor_profil_for_app (id_profil, id_application) VALUES @@ -41,14 +43,17 @@ def upgrade(): (SELECT id_profil FROM utilisateurs.t_profils WHERE code_profil = '3'), (SELECT id_application FROM utilisateurs.t_applications WHERE code_application = 'UH') ) - """) + """ + ) def downgrade(): - op.execute(""" + op.execute( + """ DELETE FROM utilisateurs.cor_profil_for_app cor USING utilisateurs.t_applications app WHERE cor.id_application = app.id_application AND app.code_application = 'UH' - """) + """ + ) op.execute("DELETE FROM utilisateurs.t_applications WHERE code_application = 'UH'") diff --git a/app/migrations/versions/f63a8f44c969_usershub_samples.py b/app/migrations/versions/f63a8f44c969_usershub_samples.py index 14ec094a..c2cdf54c 100644 --- a/app/migrations/versions/f63a8f44c969_usershub_samples.py +++ b/app/migrations/versions/f63a8f44c969_usershub_samples.py @@ -5,33 +5,37 @@ Create Date: 2021-09-06 18:17:06.392398 """ + from alembic import op import sqlalchemy as sa # revision identifiers, used by Alembic. -revision = 'f63a8f44c969' +revision = "f63a8f44c969" down_revision = None -branch_labels = ('usershub-samples',) +branch_labels = ("usershub-samples",) depends_on = ( - '9445a69f2bed', # usershub - '72f227e37bdf', # utilisateurs schema samples data + "9445a69f2bed", # usershub + "72f227e37bdf", # utilisateurs schema samples data ) def upgrade(): - op.execute(""" + op.execute( + """ INSERT INTO utilisateurs.cor_role_app_profil (id_role, id_application, id_profil) VALUES ( (SELECT id_role FROM utilisateurs.t_roles WHERE nom_role = 'Grp_admin'), (SELECT id_application FROM utilisateurs.t_applications WHERE code_application = 'UH'), (SELECT id_profil FROM utilisateurs.t_profils WHERE code_profil = '6') ) - """) + """ + ) def downgrade(): - op.execute(""" + op.execute( + """ DELETE FROM utilisateurs.cor_role_app_profil cor USING utilisateurs.t_roles r, @@ -44,4 +48,5 @@ def downgrade(): AND r.nom_role = 'Grp_admin' AND a.code_application = 'UH' AND p.code_profil = '6' - """) + """ + ) diff --git a/app/models.py b/app/models.py index e867b2f1..a335bbae 100644 --- a/app/models.py +++ b/app/models.py @@ -194,7 +194,7 @@ def get_full_name(self): Methode qui concatène le nom et prénom du role retourne un nom complet """ - return ' '.join([(self.nom_role or ''), (self.prenom_role or '')]) + return " ".join([(self.nom_role or ""), (self.prenom_role or "")]) def as_dict_full_name(self): """ @@ -298,7 +298,6 @@ def get_user_out_group(cls, id_groupe): @classmethod def get_user_profil_in_app(cls, id_application): - """ Methode qui retourne un dictionnaire de roles avec leur profil sur une application Avec pour paramètre un id d'application @@ -324,7 +323,6 @@ def get_user_profil_in_app(cls, id_application): @classmethod def get_user_profil_out_app(cls, id_application): - """ Methode qui retourne un dictionnaire de roles n'ayant pas de droits sur une application @@ -341,7 +339,6 @@ def get_user_profil_out_app(cls, id_application): @classmethod def get_groups(cls): - """ Methode qui retourne une liste des roles de type groupe @@ -352,7 +349,6 @@ def get_groups(cls): @serializable class CorRoles(GenericRepository): - """ Classe de correspondance entre un utilisateur et un groupe """ @@ -383,7 +379,6 @@ def test_role_in_grp(cls, id_role, id_group): @classmethod def add_cor(cls, id_group, ids_role): - """ Methode qui ajoute des relations roles <-> groupe Avec pour paramètres un id de groupe(id_role) @@ -398,7 +393,6 @@ def add_cor(cls, id_group, ids_role): @classmethod def del_cor(cls, id_group, ids_role): - """ Methode qui supprime des relations roles <-> groupe Avec pour paramètres un id de groupe(id_role) et un tableau @@ -414,7 +408,6 @@ def del_cor(cls, id_group, ids_role): @serializable class TListes(GenericRepository): - """ Model de la table t_listes """ @@ -429,7 +422,7 @@ class TListes(GenericRepository): @serializable class CorRoleListe(GenericRepository): - """ Classe de correspondance entre la table t_roles et la table t_listes""" + """Classe de correspondance entre la table t_roles et la table t_listes""" __tablename__ = "cor_role_liste" __table_args__ = {"schema": "utilisateurs", "extend_existing": True} @@ -470,7 +463,6 @@ def del_cor(cls, id_liste, ids_role): @serializable class TApplications(GenericRepository): - """ Model de la table t_applications """ @@ -517,7 +509,7 @@ def get_profils_in_app(cls, id_application): @classmethod def get_profil_in_app_with_code(cls, id_application, code_profil): """ - Methode qui retourne un profil à partir de son code + Methode qui retourne un profil à partir de son code """ return ( db.session.query(TProfils) @@ -560,7 +552,7 @@ def choixSelect( @serializable class CorProfilForApp(GenericRepository): - """ Classe de correspondance entre la table t_applications et la table t_profils""" + """Classe de correspondance entre la table t_applications et la table t_profils""" __tablename__ = "cor_profil_for_app" __table_args__ = {"schema": "utilisateurs", "extend_existing": True} @@ -689,4 +681,3 @@ def del_cor(cls, id_app, tab_profil): cls.id_profil == t["id_profil"] ).filter(cls.id_application == id_app).delete() db.session.commit() - diff --git a/app/t_profils/forms.py b/app/t_profils/forms.py index 21475ded..887c0581 100644 --- a/app/t_profils/forms.py +++ b/app/t_profils/forms.py @@ -7,9 +7,13 @@ class Profil(FlaskForm): """ Classe du formulaire des profils """ - id_profil = HiddenField('Id') - nom_profil = StringField('Nom', validators = [DataRequired(message = 'Le nom du profil est obligatoire')]) - code_profil = StringField('Code', validators = [DataRequired(message = 'Le code du profil est obligatoire')]) - desc_profil = StringField('Description') - submit = SubmitField('Enregistrer') + id_profil = HiddenField("Id") + nom_profil = StringField( + "Nom", validators=[DataRequired(message="Le nom du profil est obligatoire")] + ) + code_profil = StringField( + "Code", validators=[DataRequired(message="Le code du profil est obligatoire")] + ) + desc_profil = StringField("Description") + submit = SubmitField("Enregistrer") diff --git a/app/t_roles/forms.py b/app/t_roles/forms.py index dec87f97..19adb4f5 100644 --- a/app/t_roles/forms.py +++ b/app/t_roles/forms.py @@ -1,12 +1,20 @@ -''' +""" Définition du formulaire : création/modification d'un role -''' +""" from flask_wtf import FlaskForm from wtforms import ( - StringField, PasswordField, SubmitField, HiddenField, SelectField, - RadioField, BooleanField, SelectMultipleField, TextAreaField, widgets, - validators + StringField, + PasswordField, + SubmitField, + HiddenField, + SelectField, + RadioField, + BooleanField, + SelectMultipleField, + TextAreaField, + widgets, + validators, ) from wtforms.validators import DataRequired, Email @@ -17,26 +25,30 @@ class MultiCheckboxField(SelectMultipleField): class Utilisateur(FlaskForm): - active = BooleanField('Actif', default = True, false_values=(False, 'false')) - nom_role = StringField('Nom', validators=[DataRequired(message="Le nom de l'utilisateur est obligatoire")]) - prenom_role = StringField('Prenom') - desc_role = TextAreaField('Description') - id_organisme = SelectField('Organisme', coerce=int, choices=[], default=-1) - a_groupe = SelectMultipleField('', choices=[], coerce=int) - identifiant = StringField('Identifiant') - pass_plus = PasswordField('Mot de passe') - mdpconf = PasswordField('Confirmation') - email = StringField('E-mail', validators=[validators.Optional(), Email(message="L'email est incorect")]) - groupe = HiddenField('groupe', default=None) - remarques = TextAreaField('Commentaire') - id_role = HiddenField('id') - submit = SubmitField('Enregistrer') - -class UserPass(FlaskForm): - pass_plus = PasswordField('Mot de passe') - mdpconf = PasswordField('Confirmation') - id_role = HiddenField('id') - submit = SubmitField('Enregistrer') - + active = BooleanField("Actif", default=True, false_values=(False, "false")) + nom_role = StringField( + "Nom", + validators=[DataRequired(message="Le nom de l'utilisateur est obligatoire")], + ) + prenom_role = StringField("Prenom") + desc_role = TextAreaField("Description") + id_organisme = SelectField("Organisme", coerce=int, choices=[], default=-1) + a_groupe = SelectMultipleField("", choices=[], coerce=int) + identifiant = StringField("Identifiant") + pass_plus = PasswordField("Mot de passe") + mdpconf = PasswordField("Confirmation") + email = StringField( + "E-mail", + validators=[validators.Optional(), Email(message="L'email est incorect")], + ) + groupe = HiddenField("groupe", default=None) + remarques = TextAreaField("Commentaire") + id_role = HiddenField("id") + submit = SubmitField("Enregistrer") +class UserPass(FlaskForm): + pass_plus = PasswordField("Mot de passe") + mdpconf = PasswordField("Confirmation") + id_role = HiddenField("id") + submit = SubmitField("Enregistrer") diff --git a/app/t_roles/route.py b/app/t_roles/route.py index ac21ed09..bf0a3155 100644 --- a/app/t_roles/route.py +++ b/app/t_roles/route.py @@ -208,8 +208,8 @@ def updatepass(id_role=None): form = t_rolesforms.UserPass() myuser = TRoles.get_one(id_role) # Build title - role_fullname= buildUserFullName(myuser) - title=f"Changer le mot de passe de l'utilisateur '{role_fullname}'" + role_fullname = buildUserFullName(myuser) + title = f"Changer le mot de passe de l'utilisateur '{role_fullname}'" if request.method == "POST": if form.validate_on_submit() and form.validate(): @@ -282,13 +282,14 @@ def info(id_role): pathU=URL_APPLICATION + "/user/update/", ) + def buildUserFullName(user): fullname = [] if user["nom_role"]: fullname.append(user["nom_role"].upper()) if user["prenom_role"]: fullname.append(user["prenom_role"].title()) - return ' '.join(fullname) + return " ".join(fullname) def pops(form, with_group=True): diff --git a/app/utils/utilssqlalchemy.py b/app/utils/utilssqlalchemy.py index 043b11a8..df6dcf64 100644 --- a/app/utils/utilssqlalchemy.py +++ b/app/utils/utilssqlalchemy.py @@ -1,6 +1,7 @@ -''' +""" Fonctions utilitaires -''' +""" + import json from functools import wraps @@ -13,7 +14,6 @@ from sqlalchemy.orm import ColumnProperty - # def testDataType(value, sqlType, paramName): # if sqlType == DB.Integer or isinstance(sqlType, (DB.Integer)): # try: @@ -39,19 +39,20 @@ MANQUE FLOAT """ SERIALIZERS = { - 'date': lambda x: str(x) if x else None, - 'datetime': lambda x: str(x) if x else None, - 'time': lambda x: str(x) if x else None, - 'timestamp': lambda x: str(x) if x else None, - 'uuid': lambda x: str(x) if x else None + "date": lambda x: str(x) if x else None, + "datetime": lambda x: str(x) if x else None, + "time": lambda x: str(x) if x else None, + "timestamp": lambda x: str(x) if x else None, + "uuid": lambda x: str(x) if x else None, } class GenericTable: """ - Classe permettant de créer à la volée un mapping - d'une vue avec la base de données par rétroingénierie + Classe permettant de créer à la volée un mapping + d'une vue avec la base de données par rétroingénierie """ + def __init__(self, tableName, schemaName, geometry_field): meta = MetaData(schema=schemaName, bind=DB.engine) meta.reflect(views=True) @@ -64,29 +65,27 @@ def __init__(self, tableName, schemaName, geometry_field): # Mise en place d'un mapping des colonnes en vue d'une sérialisation self.serialize_columns = [ - ( - name, - SERIALIZERS.get( - db_col.type.__class__.__name__.lower(), - lambda x: x - ) - ) + (name, SERIALIZERS.get(db_col.type.__class__.__name__.lower(), lambda x: x)) for name, db_col in self.tableDef.columns.items() - if not db_col.type.__class__.__name__ == 'Geometry' + if not db_col.type.__class__.__name__ == "Geometry" ] self.columns = [column.name for column in self.tableDef.columns] def as_dict(self, data): return { - item: _serializer(getattr(data, item)) for item, _serializer in self.serialize_columns + item: _serializer(getattr(data, item)) + for item, _serializer in self.serialize_columns } + def serializeQuery(data, columnDef): rows = [ { - c['name']: getattr(row, c['name']) - for c in columnDef if getattr(row, c['name']) is not None - } for row in data + c["name"]: getattr(row, c["name"]) + for c in columnDef + if getattr(row, c["name"]) is not None + } + for row in data ] return rows @@ -96,29 +95,30 @@ def serializeQueryTest(data, columnDef): for row in data: inter = {} for c in columnDef: - if getattr(row, c['name']) is not None: - if isinstance(c['type'], (DB.Date, DB.DateTime, UUID)): - inter[c['name']] = str(getattr(row, c['name'])) - elif isinstance(c['type'], DB.Numeric): - inter[c['name']] = float(getattr(row, c['name'])) - elif not isinstance(c['type'], Geometry): - inter[c['name']] = getattr(row, c['name']) + if getattr(row, c["name"]) is not None: + if isinstance(c["type"], (DB.Date, DB.DateTime, UUID)): + inter[c["name"]] = str(getattr(row, c["name"])) + elif isinstance(c["type"], DB.Numeric): + inter[c["name"]] = float(getattr(row, c["name"])) + elif not isinstance(c["type"], Geometry): + inter[c["name"]] = getattr(row, c["name"]) rows.append(inter) return rows def serializeQueryOneResult(row, columnDef): row = { - c['name']: getattr(row, c['name']) - for c in columnDef if getattr(row, c['name']) is not None + c["name"]: getattr(row, c["name"]) + for c in columnDef + if getattr(row, c["name"]) is not None } return row def serializable(cls): """ - Décorateur de classe pour les DB.Models - Permet de rajouter la fonction as_dict qui est basée sur le mapping SQLAlchemy + Décorateur de classe pour les DB.Models + Permet de rajouter la fonction as_dict qui est basée sur le mapping SQLAlchemy """ """ @@ -131,15 +131,16 @@ def serializable(cls): db_col = prop.columns[0] # HACK # -> Récupération du nom de l'attribut sans la classe - name = str(prop).split('.', 1)[1] - if not db_col.type.__class__.__name__ == 'Geometry': - cls_db_columns.append(( - name, - SERIALIZERS.get( - db_col.type.__class__.__name__.lower(), - lambda x: x + name = str(prop).split(".", 1)[1] + if not db_col.type.__class__.__name__ == "Geometry": + cls_db_columns.append( + ( + name, + SERIALIZERS.get( + db_col.type.__class__.__name__.lower(), lambda x: x + ), ) - )) + ) """ Liste des propriétés synonymes @@ -149,17 +150,13 @@ def serializable(cls): for syn in cls.__mapper__.synonyms: col = cls.__mapper__.c[syn.name] # if column type is geometry pass - if col.type.__class__.__name__ == 'Geometry': + if col.type.__class__.__name__ == "Geometry": pass # else add synonyms in columns properties - cls_db_columns.append(( - syn.key, - SERIALIZERS.get( - col.type.__class__.__name__.lower(), - lambda x: x - ) - )) + cls_db_columns.append( + (syn.key, SERIALIZERS.get(col.type.__class__.__name__.lower(), lambda x: x)) + ) """ Liste des propriétés de type relationship @@ -187,13 +184,11 @@ def serializefn(self, recursif=False, columns=()): else: fprops = cls_db_columns - out = { - item: _serializer(getattr(self, item)) for item, _serializer in fprops - } + out = {item: _serializer(getattr(self, item)) for item, _serializer in fprops} if recursif is False: return out - for (rel, uselist) in cls_db_relationships: + for rel, uselist in cls_db_relationships: if getattr(self, rel) is None: break @@ -209,10 +204,11 @@ def serializefn(self, recursif=False, columns=()): def json_resp(fn): - ''' + """ Décorateur transformant le résultat renvoyé par une vue en objet JSON - ''' + """ + @wraps(fn) def _json_resp(*args, **kwargs): res = fn(*args, **kwargs) @@ -223,20 +219,18 @@ def _json_resp(*args, **kwargs): if not res: status = 404 - res = {'message': 'not found'} + res = {"message": "not found"} + + return Response(json.dumps(res), status=status, mimetype="application/json") - return Response( - json.dumps(res), - status=status, - mimetype='application/json' - ) return _json_resp def csv_resp(fn): - ''' + """ Décorateur transformant le résultat renvoyé en un fichier csv - ''' + """ + @wraps(fn) def _csv_resp(*args, **kwargs): res = fn(*args, **kwargs) @@ -244,20 +238,18 @@ def _csv_resp(*args, **kwargs): outdata = [separator.join(columns)] headers = Headers() - headers.add('Content-Type', 'text/plain') + headers.add("Content-Type", "text/plain") headers.add( - 'Content-Disposition', - 'attachment', - filename='export_%s.csv' % filename + "Content-Disposition", "attachment", filename="export_%s.csv" % filename ) for o in data: outdata.append( separator.join( - '"%s"' % (o.get(i), '') - [o.get(i) is None] for i in columns + '"%s"' % (o.get(i), "")[o.get(i) is None] for i in columns ) ) - out = '\r\n'.join(outdata) + out = "\r\n".join(outdata) return Response(out, headers=headers) - return _csv_resp \ No newline at end of file + + return _csv_resp From aacc8ee73314ef82cc0d83d25fb216ae78968ec2 Mon Sep 17 00:00:00 2001 From: Jacobe2169 Date: Fri, 26 Jan 2024 13:41:56 +0100 Subject: [PATCH 2/2] lint --- setup.py | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/setup.py b/setup.py index ea7ee84a..7677e24a 100644 --- a/setup.py +++ b/setup.py @@ -3,22 +3,22 @@ root_dir = Path(__file__).absolute().parent -with (root_dir / 'VERSION').open() as f: +with (root_dir / "VERSION").open() as f: version = f.read() -with (root_dir / 'README.rst').open() as f: +with (root_dir / "README.rst").open() as f: long_description = f.read() setuptools.setup( - name='usershub', - description='Application web de gestion centralisée des utilisateurs', + name="usershub", + description="Application web de gestion centralisée des utilisateurs", long_description=long_description, - long_description_content_type='text/x-rst', - maintainer='Parcs nationaux des Écrins et des Cévennes', - maintainer_email='geonature@ecrins-parcnational.fr', - url='https://github.com/PnX-SI/UsersHub', + long_description_content_type="text/x-rst", + maintainer="Parcs nationaux des Écrins et des Cévennes", + maintainer_email="geonature@ecrins-parcnational.fr", + url="https://github.com/PnX-SI/UsersHub", version=version, - packages=setuptools.find_packages(where='.', include=['app*']), + packages=setuptools.find_packages(where=".", include=["app*"]), install_requires=( list(open("requirements-common.in", "r")) + list(open("requirements-dependencies.in", "r"))