Browse Source

refactor: formating with ruff

clovis 2 months ago
parent
commit
ed45227718
38 changed files with 179 additions and 186 deletions
  1. 1 3
      alembic/env.py
  2. 1 0
      alembic/versions/2023020440_init_user_model_07c71f4389b6.py
  3. 2 3
      alembic/versions/2023080523_create_first_application_load_76f559337a4a.py
  4. 3 6
      alembic/versions/2023080645_fix_nullable_send_time_596121a6a2bc.py
  5. 1 1
      alembic/versions/2023080646_remove_unique_sms_content_33a459aac32a.py
  6. 1 0
      alembic/versions/2023080647_add_nullable_sms_volunteer_4f1ef609b19a.py
  7. 4 9
      alembic/versions/2023081625_increase_slot_datamodel_5fcd397aae72.py
  8. 3 7
      alembic/versions/2023081632_fix_slot_column_name_2f90ef72e3b9.py
  9. 5 2
      alembic/versions/2024052425_add_slot_template_4ca2e4cc7b95.py
  10. 16 7
      alembic/versions/2024060200_cascade_template_deletion_to_slot_eabd3ad5aaf8.py
  11. 0 1
      alembic/versions/2024060210_stop_cascade_template_deletion_to_slot_8fee990845df.py
  12. 1 1
      alembic/versions/2024083136_update_sms_volunteer_link_466d86d3edac.py
  13. 10 1
      app/api/api.py
  14. 1 3
      app/api/deps.py
  15. 8 8
      app/api/endpoints/project.py
  16. 3 9
      app/api/endpoints/slots.py
  17. 4 8
      app/api/endpoints/sms.py
  18. 10 2
      app/api/endpoints/tags.py
  19. 1 3
      app/api/endpoints/templates.py
  20. 0 1
      app/api/endpoints/volunteers.py
  21. 1 3
      app/core/config.py
  22. 1 0
      app/core/session.py
  23. 3 5
      app/create_sms_batch.py
  24. 2 6
      app/importData/gsheet.py
  25. 2 1
      app/models.py
  26. 2 6
      app/restore_project.py
  27. 1 3
      app/schemas/requests.py
  28. 1 1
      app/tests/test_project.py
  29. 11 27
      app/tests/test_slot.py
  30. 6 18
      app/tests/test_sms.py
  31. 4 1
      app/tests/test_sms_batch.py
  32. 7 4
      app/tests/test_tag.py
  33. 6 18
      app/tests/test_template.py
  34. 3 9
      app/tests/test_users.py
  35. 2 2
      app/tests/test_volunteer.py
  36. 42 4
      pyproject.toml
  37. 9 2
      script/KdeConnect.py
  38. 1 1
      script/send_sms.py

+ 1 - 3
alembic/env.py

@@ -59,9 +59,7 @@ def run_migrations_offline():
 
 
 def do_run_migrations(connection):
-    context.configure(
-        connection=connection, target_metadata=target_metadata, compare_type=True
-    )
+    context.configure(connection=connection, target_metadata=target_metadata, compare_type=True)
 
     with context.begin_transaction():
         context.run_migrations()

+ 1 - 0
alembic/versions/2023020440_init_user_model_07c71f4389b6.py

@@ -5,6 +5,7 @@ Revises:
 Create Date: 2023-02-04 23:40:00.426237
 
 """
+
 import sqlalchemy as sa
 
 from alembic import op

+ 2 - 3
alembic/versions/2023080523_create_first_application_load_76f559337a4a.py

@@ -5,6 +5,7 @@ Revises: 07c71f4389b6
 Create Date: 2023-08-05 21:23:21.563804
 
 """
+
 from alembic import op
 import sqlalchemy as sa
 
@@ -75,9 +76,7 @@ def upgrade():
         sa.Column("volunteer_id", sa.UUID(as_uuid=False), nullable=False),
         sa.Column("slot_id", sa.UUID(as_uuid=False), nullable=False),
         sa.ForeignKeyConstraint(["slot_id"], ["slots.id"], ondelete="CASCADE"),
-        sa.ForeignKeyConstraint(
-            ["volunteer_id"], ["volunteers.id"], ondelete="CASCADE"
-        ),
+        sa.ForeignKeyConstraint(["volunteer_id"], ["volunteers.id"], ondelete="CASCADE"),
         sa.PrimaryKeyConstraint("volunteer_id", "slot_id"),
     )
     op.create_table(

+ 3 - 6
alembic/versions/2023080645_fix_nullable_send_time_596121a6a2bc.py

@@ -5,6 +5,7 @@ Revises: 76f559337a4a
 Create Date: 2023-08-06 09:45:00.639402
 
 """
+
 from alembic import op
 import sqlalchemy as sa
 from sqlalchemy.dialects import postgresql
@@ -24,17 +25,13 @@ def upgrade():
         existing_type=postgresql.TIMESTAMP(timezone=True),
         nullable=True,
     )
-    op.alter_column(
-        "volunteers", "surname", existing_type=sa.VARCHAR(length=128), nullable=True
-    )
+    op.alter_column("volunteers", "surname", existing_type=sa.VARCHAR(length=128), nullable=True)
     # ### end Alembic commands ###
 
 
 def downgrade():
     # ### commands auto generated by Alembic - please adjust! ###
-    op.alter_column(
-        "volunteers", "surname", existing_type=sa.VARCHAR(length=128), nullable=False
-    )
+    op.alter_column("volunteers", "surname", existing_type=sa.VARCHAR(length=128), nullable=False)
     op.alter_column(
         "sms",
         "send_time",

+ 1 - 1
alembic/versions/2023080646_remove_unique_sms_content_33a459aac32a.py

@@ -5,8 +5,8 @@ Revises: 596121a6a2bc
 Create Date: 2023-08-06 09:46:46.191884
 
 """
+
 from alembic import op
-import sqlalchemy as sa
 
 
 # revision identifiers, used by Alembic.

+ 1 - 0
alembic/versions/2023080647_add_nullable_sms_volunteer_4f1ef609b19a.py

@@ -5,6 +5,7 @@ Revises: 33a459aac32a
 Create Date: 2023-08-06 09:47:34.658536
 
 """
+
 from alembic import op
 import sqlalchemy as sa
 

+ 4 - 9
alembic/versions/2023081625_increase_slot_datamodel_5fcd397aae72.py

@@ -5,6 +5,7 @@ Revises: 4f1ef609b19a
 Create Date: 2023-08-16 22:25:30.650590
 
 """
+
 from alembic import op
 import sqlalchemy as sa
 
@@ -18,24 +19,18 @@ depends_on = None
 
 def upgrade():
     # ### commands auto generated by Alembic - please adjust! ###
-    op.add_column(
-        "slots", sa.Column("place", sa.String(), nullable=False, server_default="")
-    )
+    op.add_column("slots", sa.Column("place", sa.String(), nullable=False, server_default=""))
     op.add_column(
         "slots",
         sa.Column("responsibleContact", sa.String(), nullable=False, server_default=""),
     )
-    op.alter_column(
-        "volunteers", "surname", existing_type=sa.VARCHAR(length=128), nullable=False
-    )
+    op.alter_column("volunteers", "surname", existing_type=sa.VARCHAR(length=128), nullable=False)
     # ### end Alembic commands ###
 
 
 def downgrade():
     # ### commands auto generated by Alembic - please adjust! ###
-    op.alter_column(
-        "volunteers", "surname", existing_type=sa.VARCHAR(length=128), nullable=True
-    )
+    op.alter_column("volunteers", "surname", existing_type=sa.VARCHAR(length=128), nullable=True)
     op.drop_column("slots", "responsibleContact")
     op.drop_column("slots", "place")
     # ### end Alembic commands ###

+ 3 - 7
alembic/versions/2023081632_fix_slot_column_name_2f90ef72e3b9.py

@@ -5,8 +5,8 @@ Revises: 5fcd397aae72
 Create Date: 2023-08-16 22:32:42.841398
 
 """
+
 from alembic import op
-import sqlalchemy as sa
 
 
 # revision identifiers, used by Alembic.
@@ -18,16 +18,12 @@ depends_on = None
 
 def upgrade():
     # ### commands auto generated by Alembic - please adjust! ###
-    op.alter_column(
-        "slots", "responsibleContact", new_column_name="responsible_contact"
-    )
+    op.alter_column("slots", "responsibleContact", new_column_name="responsible_contact")
     # ### end Alembic commands ###
 
 
 def downgrade():
     # ### commands auto generated by Alembic - please adjust! ###
 
-    op.alter_column(
-        "slots", "responsible_contact", new_column_name="responsibleContact"
-    )
+    op.alter_column("slots", "responsible_contact", new_column_name="responsibleContact")
     # ### end Alembic commands ###

+ 5 - 2
alembic/versions/2024052425_add_slot_template_4ca2e4cc7b95.py

@@ -5,6 +5,7 @@ Revises: 2f90ef72e3b9
 Create Date: 2024-05-24 09:25:42.163966
 
 """
+
 from datetime import datetime
 from typing import List, Optional
 from alembic import op
@@ -115,7 +116,8 @@ def upgrade():
         sa.PrimaryKeyConstraint("description_id", "tag_id"),
     )
     op.add_column(
-        "slots", sa.Column("required_volunteers", sa.Integer(), nullable=False, server_default="0")
+        "slots",
+        sa.Column("required_volunteers", sa.Integer(), nullable=False, server_default="0"),
     )
     op.alter_column("slots", "required_volunteers", server_default=None)
     op.add_column("slots", sa.Column("template_id", sa.UUID(as_uuid=False), nullable=True))
@@ -164,7 +166,8 @@ def downgrade():
         ),
     )
     op.add_column(
-        "slots", sa.Column("description", sa.VARCHAR(), autoincrement=False, nullable=False)
+        "slots",
+        sa.Column("description", sa.VARCHAR(), autoincrement=False, nullable=False),
     )
 
     # Revert data from template to slot

+ 16 - 7
alembic/versions/2024060200_cascade_template_deletion_to_slot_eabd3ad5aaf8.py

@@ -5,26 +5,35 @@ Revises: 4ca2e4cc7b95
 Create Date: 2024-06-02 16:00:29.689607
 
 """
+
 from alembic import op
-import sqlalchemy as sa
 
 
 # revision identifiers, used by Alembic.
-revision = 'eabd3ad5aaf8'
-down_revision = '4ca2e4cc7b95'
+revision = "eabd3ad5aaf8"
+down_revision = "4ca2e4cc7b95"
 branch_labels = None
 depends_on = None
 
 
 def upgrade():
     # ### commands auto generated by Alembic - please adjust! ###
-    op.drop_constraint('slots_template_id_fkey', 'slots', type_='foreignkey')
-    op.create_foreign_key('slots_template_id_fkey_v2', 'slots', 'slot_templates', ['template_id'], ['id'], ondelete='CASCADE')
+    op.drop_constraint("slots_template_id_fkey", "slots", type_="foreignkey")
+    op.create_foreign_key(
+        "slots_template_id_fkey_v2",
+        "slots",
+        "slot_templates",
+        ["template_id"],
+        ["id"],
+        ondelete="CASCADE",
+    )
     # ### end Alembic commands ###
 
 
 def downgrade():
     # ### commands auto generated by Alembic - please adjust! ###
-    op.drop_constraint('slots_template_id_fkey_v2', 'slots', type_='foreignkey')
-    op.create_foreign_key('slots_template_id_fkey', 'slots', 'slot_templates', ['template_id'], ['id'])
+    op.drop_constraint("slots_template_id_fkey_v2", "slots", type_="foreignkey")
+    op.create_foreign_key(
+        "slots_template_id_fkey", "slots", "slot_templates", ["template_id"], ["id"]
+    )
     # ### end Alembic commands ###

+ 0 - 1
alembic/versions/2024060210_stop_cascade_template_deletion_to_slot_8fee990845df.py

@@ -7,7 +7,6 @@ Create Date: 2024-06-02 17:10:22.363720
 """
 
 from alembic import op
-import sqlalchemy as sa
 
 
 # revision identifiers, used by Alembic.

+ 1 - 1
alembic/versions/2024083136_update_sms_volunteer_link_466d86d3edac.py

@@ -5,8 +5,8 @@ Revises: f058df5a266c
 Create Date: 2024-08-31 14:36:54.062147
 
 """
+
 from alembic import op
-import sqlalchemy as sa
 
 
 # revision identifiers, used by Alembic.

+ 10 - 1
app/api/api.py

@@ -1,6 +1,15 @@
 from fastapi import APIRouter
 
-from app.api.endpoints import auth, project, slots, users, volunteers, sms, tags, templates
+from app.api.endpoints import (
+    auth,
+    project,
+    slots,
+    users,
+    volunteers,
+    sms,
+    tags,
+    templates,
+)
 
 api_router = APIRouter()
 api_router.include_router(auth.router, prefix="/auth", tags=["auth"])

+ 1 - 3
app/api/deps.py

@@ -23,9 +23,7 @@ async def get_current_user(
     session: Session = Depends(get_session), token: str = Depends(reusable_oauth2)
 ) -> User:
     try:
-        payload = jwt.decode(
-            token, config.settings.SECRET_KEY, algorithms=[security.JWT_ALGORITHM]
-        )
+        payload = jwt.decode(token, config.settings.SECRET_KEY, algorithms=[security.JWT_ALGORITHM])
     except jwt.DecodeError:
         raise HTTPException(
             status_code=status.HTTP_403_FORBIDDEN,

+ 8 - 8
app/api/endpoints/project.py

@@ -42,7 +42,7 @@ async def list_public_project(
     session: Session = Depends(deps.get_session),
 ):
     """Get the list of public projects"""
-    results = session.execute(select(Project).where(Project.is_public == True))
+    results = session.execute(select(Project).where(Project.is_public))
     return results.scalars().all()
 
 
@@ -57,7 +57,7 @@ async def create_project(
     session.add(project)
     try:
         session.commit()
-    except IntegrityError as e:
+    except IntegrityError:
         raise HTTPException(400, "Project name already exist")
 
     session.refresh(project)
@@ -244,9 +244,9 @@ async def create_sms_batch(
             .replace("{fin}", slot.ending_time.strftime("%Hh%M"))
         )
         if slot.template is not None:
-            slot_content = slot_content.replace(
-                "{description}", slot.template.description
-            ).replace("{respo}", slot.template.responsible_contact)
+            slot_content = slot_content.replace("{description}", slot.template.description).replace(
+                "{respo}", slot.template.responsible_contact
+            )
 
         sending_time = slot.starting_time - timedelta(minutes=sms_batch.delta_t)
         # Skip SMS that should have been send before now
@@ -256,9 +256,9 @@ async def create_sms_batch(
             if not volunteer.automatic_sms:
                 continue
             # Create a new SMS customized for each user attache to the slot
-            personalized_content = slot_content.replace(
-                "{prenom}", volunteer.name
-            ).replace("{nom}", volunteer.surname)
+            personalized_content = slot_content.replace("{prenom}", volunteer.name).replace(
+                "{nom}", volunteer.surname
+            )
             sms = Sms(
                 project_id=project_id,
                 volunteer_id=volunteer.id,

+ 3 - 9
app/api/endpoints/slots.py

@@ -55,9 +55,7 @@ async def create_slot(
     volunteers: list[UUID] = []
     if input_dict["volunteers"] is not None:
         volunteers = input_dict["volunteers"]
-        await verify_id_list(
-            session, volunteers, project_id, Volunteer, "Invalid volunteer list"
-        )
+        await verify_id_list(session, volunteers, project_id, Volunteer, "Invalid volunteer list")
     del input_dict["volunteers"]
 
     slot = Slot(project_id=project_id, **input_dict)
@@ -100,9 +98,7 @@ async def update_slot(
     input_dict = new_slot.model_dump(exclude_unset=True)
     if "volunteers" in input_dict:
         volunteers: list[UUID] = input_dict["volunteers"]
-        await verify_id_list(
-            session, volunteers, project_id, Volunteer, "Invalid volunteer list"
-        )
+        await verify_id_list(session, volunteers, project_id, Volunteer, "Invalid volunteer list")
         session.execute(
             association_table_volunteer_slot.delete().where(
                 association_table_volunteer_slot.c.slot_id == slot.id
@@ -136,7 +132,5 @@ async def delete_slot(
     session: Session = Depends(deps.get_session),
 ):
     """Delete a slot from the project"""
-    session.execute(
-        delete(Slot).where((Slot.id == slot_id) & (Slot.project_id == project_id))
-    )
+    session.execute(delete(Slot).where((Slot.id == slot_id) & (Slot.project_id == project_id)))
     session.commit()

+ 4 - 8
app/api/endpoints/sms.py

@@ -77,9 +77,7 @@ async def delete_sms(
     session: Session = Depends(deps.get_session),
 ):
     """Delete a sms from the project"""
-    session.execute(
-        delete(Sms).where((Sms.id == sms_id) & (Sms.project_id == str(project_id)))
-    )
+    session.execute(delete(Sms).where((Sms.id == sms_id) & (Sms.project_id == str(project_id))))
     session.commit()
 
 
@@ -99,7 +97,7 @@ async def list_sms_to_send(
         select(Sms).where(
             (Sms.sending_time > min_sending_time)
             & (Sms.sending_time < now)
-            & (Sms.send_time == None)
+            & (Sms.send_time == None)  # noqa: E711
         )
     )
     return results.scalars().all()
@@ -129,7 +127,7 @@ async def list_not_sent(
     session: Session = Depends(deps.get_session),
 ):
     """List sms that are not sent"""
-    results = session.execute(select(Sms).where((Sms.send_time == None)))
+    results = session.execute(select(Sms).where((Sms.send_time == None)))  # noqa: E711
     return results.scalars().all()
 
 
@@ -139,7 +137,5 @@ async def list_future_sms(
     session: Session = Depends(deps.get_session),
 ):
     """List sms that should be sent in the future"""
-    results = session.execute(
-        select(Sms).where(Sms.sending_time > datetime.datetime.now())
-    )
+    results = session.execute(select(Sms).where(Sms.sending_time > datetime.datetime.now()))
     return results.scalars().all()

+ 10 - 2
app/api/endpoints/tags.py

@@ -50,7 +50,11 @@ async def create_tag(
 
     if payload.templates is not None and len(payload.templates) > 0:
         await verify_id_list(
-            session, payload.templates, project_id, SlotTemplate, "Invalid template list"
+            session,
+            payload.templates,
+            project_id,
+            SlotTemplate,
+            "Invalid template list",
         )
         session.execute(
             association_table_template_tags.insert().values(
@@ -86,7 +90,11 @@ async def update_tag(
         )
         if len(payload.templates) > 0:
             await verify_id_list(
-                session, payload.templates, project_id, SlotTemplate, "Invalid template list"
+                session,
+                payload.templates,
+                project_id,
+                SlotTemplate,
+                "Invalid template list",
             )
             session.execute(
                 association_table_template_tags.insert().values(

+ 1 - 3
app/api/endpoints/templates.py

@@ -66,9 +66,7 @@ async def create_template(
     return template
 
 
-@router.post(
-    "/project/{project_id}/template/{template_id}", response_model=TemplateResponse
-)
+@router.post("/project/{project_id}/template/{template_id}", response_model=TemplateResponse)
 async def update_template(
     project_id: UUID,
     template_id: UUID,

+ 0 - 1
app/api/endpoints/volunteers.py

@@ -3,7 +3,6 @@ from uuid import UUID
 from fastapi import APIRouter, Depends, HTTPException
 from sqlalchemy import delete, select
 from sqlalchemy.orm import Session
-from sqlalchemy.sql import func
 
 from app.api import deps
 from app.api.utils import update_object_from_payload, verify_id_list

+ 1 - 3
app/core/config.py

@@ -93,9 +93,7 @@ class Settings(BaseSettings):
     FIRST_SUPERUSER_EMAIL: EmailStr
     FIRST_SUPERUSER_PASSWORD: str
 
-    model_config = SettingsConfigDict(
-        env_file=f"{PROJECT_DIR}/.env", case_sensitive=True
-    )
+    model_config = SettingsConfigDict(env_file=f"{PROJECT_DIR}/.env", case_sensitive=True)
 
 
 settings: Settings = Settings()  # type: ignore

+ 1 - 0
app/core/session.py

@@ -1,6 +1,7 @@
 """
 SQLAlchemy  engine and sessions tools
 """
+
 from sqlalchemy import create_engine
 from sqlalchemy.orm import sessionmaker
 

+ 3 - 5
app/create_sms_batch.py

@@ -1,12 +1,10 @@
-"""
-
-"""
+""" """
 
 from sqlalchemy import select
 from datetime import datetime, timedelta
-from app.core import config, security
+from app.core import config
 from app.core.session import session
-from app.models import User, Sms, Project
+from app.models import Sms, Project
 
 TEST_SMS_PROJECT_NAME = "test_project pour sms"
 NUMBER_OF_SMS = 80

+ 2 - 6
app/importData/gsheet.py

@@ -116,9 +116,7 @@ def downloadAndSave(doc_ui: str, sheet_gid: str, file: Union[str, bytes, os.Path
         f.write(rep.content)
 
 
-def getContactDataFrame(
-    csv_filename: str, skiprows: int = 2
-) -> DataFrame[ContactSchema]:
+def getContactDataFrame(csv_filename: str, skiprows: int = 2) -> DataFrame[ContactSchema]:
     df_contact = pd.read_csv(csv_filename, skiprows=skiprows)
     column_to_drop = [name for name in df_contact.columns if "Unnamed" in name]
     df_contact.drop(column_to_drop, axis=1, inplace=True)
@@ -201,9 +199,7 @@ def getPlanningDataFrame(
         current_benevole_name = ""
         current_time: dict[str, datetime.datetime] = {}
         for j in range(skip_column, len(row)):
-            if (current_benevole_name != "") and (
-                row[j] == "" or row[j] != current_benevole_name
-            ):
+            if (current_benevole_name != "") and (row[j] == "" or row[j] != current_benevole_name):
                 new_creneau = {
                     "id": str(uuid4()),
                     "template_id": row[0],

+ 2 - 1
app/models.py

@@ -214,7 +214,8 @@ class Sms(Base):
     project: Mapped["Project"] = relationship(back_populates="sms")
 
     volunteer_id: Mapped[str] = mapped_column(
-        ForeignKey("volunteers.id", ondelete="CASCADE", onupdate="CASCADE"), nullable=True
+        ForeignKey("volunteers.id", ondelete="CASCADE", onupdate="CASCADE"),
+        nullable=True,
     )
     volunteer: Mapped["Volunteer"] = relationship(back_populates="sms", cascade="all, delete")
     created_at: Mapped[datetime] = mapped_column(DateTime(timezone=True), server_default=func.now())

+ 2 - 6
app/restore_project.py

@@ -1,12 +1,8 @@
-"""
-
-"""
+""" """
 
 from sqlalchemy import select
-from datetime import datetime, timedelta
-from app.core import config, security
 from app.core.session import session
-from app.models import User, Sms, Project
+from app.models import Project
 
 TEST_SMS_PROJECT_NAME = "522e62c3-9620-47e1-bdd6-d856095533e7"
 NUMBER_OF_SMS = 80

+ 1 - 3
app/schemas/requests.py

@@ -62,9 +62,7 @@ class ProjectSMSBatchRequest(BaseRequest):
      - {respo} slot.responsible_contact
      - {prenom} volunteer.name
      - {nom} volunteer.surname""",
-        examples=[
-            "Bonjour {prenom},\nTon créneau {titre} commence à {debut}.\nla com bénévole"
-        ],
+        examples=["Bonjour {prenom},\nTon créneau {titre} commence à {debut}.\nla com bénévole"],
     )
     delta_t: int = Field(
         default=10,

+ 1 - 1
app/tests/test_project.py

@@ -96,7 +96,7 @@ async def test_create_project(client: AsyncClient, default_user_headers: dict, s
     result = session.execute(select(Project).where(Project.name == "Coucou"))
     project = result.scalars().first()
     assert project is not None
-    assert project.is_public == False
+    assert not project.is_public
 
     # Create a public project
     response = await client.post(

+ 11 - 27
app/tests/test_slot.py

@@ -52,9 +52,7 @@ async def test_create_slot(
     session: Session,
 ):
     # Test without autentication
-    response = await client.post(
-        app.url_path_for("create_slot", project_id=default_project_id)
-    )
+    response = await client.post(app.url_path_for("create_slot", project_id=default_project_id))
     assert response.status_code == 401
     starting_time = datetime(1900, 1, 1)
     payload = {
@@ -86,9 +84,9 @@ async def test_create_slot(
     slot = [s for s in slots if s.id != default_slot_id][0]
     assert slot.title == "être mort"
     assert slot.required_volunteers == 0
-    assert abs(
-        slot.starting_time - starting_time.replace(tzinfo=timezone.utc)
-    ) < timedelta(minutes=30)
+    assert abs(slot.starting_time - starting_time.replace(tzinfo=timezone.utc)) < timedelta(
+        minutes=30
+    )
 
     # Test invalid payload
     del payload["title"]
@@ -191,9 +189,7 @@ async def test_update_slot(
         assert response.status_code == 200
         assert response.json()["id"] == default_slot_id
         if "time" in k:
-            assert datetime.fromisoformat(response.json()[k]) == datetime.fromisoformat(
-                v
-            )
+            assert datetime.fromisoformat(response.json()[k]) == datetime.fromisoformat(v)
         else:
             assert response.json()[k] == v
 
@@ -214,9 +210,7 @@ async def test_update_slot_remove_template(
         headers=default_user_headers,
     )
     assert response.status_code == 200
-    slot = session.execute(
-        select(Slot).where(Slot.project_id == default_project_id)
-    ).scalar_one()
+    slot = session.execute(select(Slot).where(Slot.project_id == default_project_id)).scalar_one()
     assert slot.template_id == default_template_id
 
     response = await client.post(
@@ -310,9 +304,7 @@ async def test_update_slot_volunteers(
     )
 
     assert response.status_code == 200
-    result = session.execute(
-        select(Volunteer).where(Volunteer.id == default_volunteer_id)
-    )
+    result = session.execute(select(Volunteer).where(Volunteer.id == default_volunteer_id))
     volunteer = result.scalars().first()
     assert volunteer is not None
     assert volunteer.slots_id == []
@@ -380,9 +372,7 @@ async def test_delete_slot_fail(
 
     # Cannot delete non uuid string
     response = await client.delete(
-        app.url_path_for(
-            "delete_slot", project_id=default_project_id, slot_id="not uidstr"
-        ),
+        app.url_path_for("delete_slot", project_id=default_project_id, slot_id="not uidstr"),
         headers=default_user_headers,
     )
     assert response.status_code == 422
@@ -409,18 +399,14 @@ async def test_delete_slot(
     assert slot is None
 
     # check deletion is cascaded to volunteers
-    result = session.execute(
-        select(Volunteer).where(Volunteer.id == default_volunteer_id)
-    )
+    result = session.execute(select(Volunteer).where(Volunteer.id == default_volunteer_id))
     volunteer: Volunteer | None = result.scalars().first()
     assert volunteer is not None
     assert default_slot_id not in volunteer.slots_id
 
     # can delete random uuid
     response = await client.delete(
-        app.url_path_for(
-            "delete_slot", project_id=default_project_id, slot_id=uuid.uuid4()
-        ),
+        app.url_path_for("delete_slot", project_id=default_project_id, slot_id=uuid.uuid4()),
         headers=default_user_headers,
     )
     assert response.status_code == 200
@@ -433,9 +419,7 @@ async def test_delete_slot_idempotent(
     default_public_project: Project,
 ):
     # Idempotence test
-    url = app.url_path_for(
-        "delete_slot", project_id=default_project_id, slot_id=default_slot_id
-    )
+    url = app.url_path_for("delete_slot", project_id=default_project_id, slot_id=default_slot_id)
     response = await client.delete(url, headers=default_user_headers)
     response = await client.delete(url, headers=default_user_headers)
     assert response.status_code == 200

+ 6 - 18
app/tests/test_sms.py

@@ -44,9 +44,7 @@ async def test_create_sms(
     session: Session,
 ):
     # Test without autentication
-    response = await client.post(
-        app.url_path_for("create_sms", project_id=default_project_id)
-    )
+    response = await client.post(app.url_path_for("create_sms", project_id=default_project_id))
     assert response.status_code == 401
     payload = {"phone_number": "06 75 75 75 75 ", "content": "sms_content"}
     # test invalid project_id
@@ -67,9 +65,7 @@ async def test_create_sms(
     assert response.status_code == 200
     assert response.json()["content"] == "sms_content"
     result = session.execute(
-        select(Sms).where(
-            (Sms.project_id == default_project_id) & (Sms.id != default_sms_id)
-        )
+        select(Sms).where((Sms.project_id == default_project_id) & (Sms.id != default_sms_id))
     )
     sms = result.scalars().first()
 
@@ -213,18 +209,14 @@ async def test_delete_sms(
 
     # can delete random uuid
     response = await client.delete(
-        app.url_path_for(
-            "delete_sms", project_id=default_project_id, sms_id=uuid.uuid4()
-        ),
+        app.url_path_for("delete_sms", project_id=default_project_id, sms_id=uuid.uuid4()),
         headers=default_user_headers,
     )
     assert response.status_code == 200
 
     # Cannot delete non uuid string
     response = await client.delete(
-        app.url_path_for(
-            "delete_sms", project_id=default_project_id, sms_id="not uidstr"
-        ),
+        app.url_path_for("delete_sms", project_id=default_project_id, sms_id="not uidstr"),
         headers=default_user_headers,
     )
     assert response.status_code == 422
@@ -236,9 +228,7 @@ async def test_delete_sms_with_volunteer(
     session: Session,
     default_public_project: Project,
 ):
-    result = session.execute(
-        select(Volunteer).where(Volunteer.id == default_volunteer_id)
-    )
+    result = session.execute(select(Volunteer).where(Volunteer.id == default_volunteer_id))
     volunteer = result.scalars().first()
     assert volunteer is not None
     assert len(volunteer.sms) == 0
@@ -267,9 +257,7 @@ async def test_delete_sms_with_volunteer(
     session.refresh(volunteer)
     assert len(volunteer.sms) == 0, "Sms should be deleted"
 
-    result = session.execute(
-        select(Volunteer).where(Volunteer.id == default_volunteer_id)
-    )
+    result = session.execute(select(Volunteer).where(Volunteer.id == default_volunteer_id))
     volunteer_result = result.scalars().first()
     assert volunteer_result is not None, "Volunteer should not be deleted"
     assert len(volunteer_result.sms) == 0, "No more sms associated to volunteer"

+ 4 - 1
app/tests/test_sms_batch.py

@@ -225,7 +225,10 @@ starting_time = datetime.now() + timedelta(minutes=30)
         ("{prenom}", "Arthur"),
         ("{prenom} {nom}", "Arthur Pandragon"),
         ("{debut}", starting_time.strftime("%Hh%M")),
-        ("{titre} {description}, {respo}", "replanter excalibure {description}, {respo}"),
+        (
+            "{titre} {description}, {respo}",
+            "replanter excalibure {description}, {respo}",
+        ),
     ],
 )
 async def test_content_no_template(

+ 7 - 4
app/tests/test_tag.py

@@ -1,5 +1,4 @@
-from datetime import datetime, timezone
-from re import template
+from datetime import datetime
 import uuid
 from httpx import AsyncClient
 import pytest
@@ -103,7 +102,9 @@ async def test_create_tag_with_template(
     session: Session,
 ):
     template = SlotTemplate(
-        project_id=default_project_id, title="coucou", description="ceci est une description"
+        project_id=default_project_id,
+        title="coucou",
+        description="ceci est une description",
     )
     session.add(template)
     session.commit()
@@ -119,7 +120,9 @@ async def test_create_tag_with_template(
     assert len(template.tags) > 0
 
     template = SlotTemplate(
-        project_id=default_project_id, title="coucou", description="ceci est une description"
+        project_id=default_project_id,
+        title="coucou",
+        description="ceci est une description",
     )
     session.add(template)
     session.commit()

+ 6 - 18
app/tests/test_template.py

@@ -22,9 +22,7 @@ async def test_create_template_fail(
     assert response.status_code == 422
 
     url = app.url_path_for("create_template", project_id=uuid4())
-    response = await client.post(
-        url, json={"title": "1st template"}, headers=default_user_headers
-    )
+    response = await client.post(url, json={"title": "1st template"}, headers=default_user_headers)
     assert response.status_code == 404
 
 
@@ -82,9 +80,7 @@ async def test_update_template_fail(
     response = await client.post(url, json=payload, headers=default_user_headers)
     assert response.status_code == 404
 
-    url = app.url_path_for(
-        "update_template", project_id=uuid4(), template_id=template_id
-    )
+    url = app.url_path_for("update_template", project_id=uuid4(), template_id=template_id)
     response = await client.post(url, json=payload, headers=default_user_headers)
     assert response.status_code == 404
 
@@ -197,16 +193,12 @@ async def test_delete_template_fail(
     response = await client.delete(url)
     assert response.status_code == 401
     # invalid tag
-    url = app.url_path_for(
-        "delete_template", project_id=project_id, template_id="default_tag_id"
-    )
+    url = app.url_path_for("delete_template", project_id=project_id, template_id="default_tag_id")
     response = await client.delete(url, headers=default_user_headers)
     assert response.status_code == 422
 
     # invalid project_id
-    url = app.url_path_for(
-        "delete_template", project_id="ded", template_id=default_template_id
-    )
+    url = app.url_path_for("delete_template", project_id="ded", template_id=default_template_id)
     response = await client.delete(url, headers=default_user_headers)
     assert response.status_code == 422
 
@@ -225,16 +217,12 @@ async def test_delete_template(
     )
     response = await client.delete(url, headers=default_user_headers)
     assert response.status_code == 200
-    result = session.execute(
-        select(SlotTemplate).where(SlotTemplate.id == default_tag_id)
-    )
+    result = session.execute(select(SlotTemplate).where(SlotTemplate.id == default_tag_id))
     slot = result.scalars().first()
     assert slot is None
 
     # can delete random uuid
-    url = app.url_path_for(
-        "delete_tag", project_id=default_public_project.id, tag_id=uuid4()
-    )
+    url = app.url_path_for("delete_tag", project_id=default_public_project.id, tag_id=uuid4())
     response = await client.delete(url, headers=default_user_headers)
     assert response.status_code == 200
 

+ 3 - 9
app/tests/test_users.py

@@ -12,9 +12,7 @@ from app.tests.conftest import (
 
 
 async def test_read_current_user(client: AsyncClient, default_user_headers):
-    response = await client.get(
-        app.url_path_for("read_current_user"), headers=default_user_headers
-    )
+    response = await client.get(app.url_path_for("read_current_user"), headers=default_user_headers)
     assert response.status_code == 200
     assert response.json() == {
         "id": default_user_id,
@@ -22,9 +20,7 @@ async def test_read_current_user(client: AsyncClient, default_user_headers):
     }
 
 
-async def test_delete_current_user(
-    client: AsyncClient, default_user_headers, session: Session
-):
+async def test_delete_current_user(client: AsyncClient, default_user_headers, session: Session):
     response = await client.delete(
         app.url_path_for("delete_current_user"), headers=default_user_headers
     )
@@ -49,9 +45,7 @@ async def test_reset_current_user_password(
     assert user.hashed_password != default_user_password_hash
 
 
-async def test_register_new_user(
-    client: AsyncClient, default_user_headers, session: Session
-):
+async def test_register_new_user(client: AsyncClient, default_user_headers, session: Session):
     response = await client.post(
         app.url_path_for("register_new_user"),
         headers=default_user_headers,

+ 2 - 2
app/tests/test_volunteer.py

@@ -1,10 +1,10 @@
 import uuid
 from httpx import AsyncClient
-from sqlalchemy import false, select
+from sqlalchemy import select
 from sqlalchemy.orm import Session
 
 from app.main import app
-from app.models import Project, Slot, Sms, User, Volunteer
+from app.models import Project, Slot, Sms, Volunteer
 from app.tests.conftest import (
     default_project_id,
     default_volunteer_id,

+ 42 - 4
pyproject.toml

@@ -41,8 +41,46 @@ markers = ["pytest.mark.asyncio"]
 minversion = "6.0"
 testpaths = ["app/tests"]
 
-[tool.isort]
-profile = "black"
-
-[tool.black]
+[tool.ruff]
+# Exclude a variety of commonly ignored directories.
+exclude = [
+    ".bzr",
+    ".direnv",
+    ".eggs",
+    ".git",
+    ".git-rewrite",
+    ".hg",
+    ".ipynb_checkpoints",
+    ".mypy_cache",
+    ".nox",
+    ".pants.d",
+    ".pyenv",
+    ".pytest_cache",
+    ".pytype",
+    ".ruff_cache",
+    ".svn",
+    ".tox",
+    ".venv",
+    ".vscode",
+    "__pypackages__",
+    "_build",
+    "buck-out",
+    "build",
+    "dist",
+    "node_modules",
+    "site-packages",
+    "venv",
+]
 line-length = 100
+indent-width = 4
+target-version = "py311"
+
+[tool.ruff.format]
+skip-magic-trailing-comma = false
+line-ending = "auto"
+
+[tool.ruff.lint.isort]
+combine-as-imports = false
+
+[tool.ruff.lint.per-file-ignores]
+"__init__.py" = ["E402"]

+ 9 - 2
script/KdeConnect.py

@@ -33,7 +33,7 @@ class KDEConnect:
         try:
             # Verify kdeconnect is available
             KDEConnect.run_kde_command(["-v"])
-        except FileNotFoundError as e:
+        except FileNotFoundError:
             raise KDEConnectError("KDEconnect-cli is not available on this computer")
 
         # verify the device exist
@@ -57,7 +57,14 @@ class KDEConnect:
     def send_sms(self, phone_number: str, sms_content: str):
         # Compact phone number by removing space
         phone = re.sub("[^+0-9]", "", phone_number)
-        command = ["-d", self.device.id, "--send-sms", sms_content, "--destination", phone]
+        command = [
+            "-d",
+            self.device.id,
+            "--send-sms",
+            sms_content,
+            "--destination",
+            phone,
+        ]
         KDEConnect.run_kde_command(command)
 
     @staticmethod

+ 1 - 1
script/send_sms.py

@@ -65,7 +65,7 @@ if __name__ == "__main__":
         starting_time = time.time()
         try:
             main()
-        except Exception as e:
+        except Exception:
             logging.exception("An error as occured : ")
         elapsed_time = time.time() - starting_time
         time.sleep(180 - elapsed_time)