diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml
index 7acd3bd6..84a17a15 100644
--- a/.pre-commit-config.yaml
+++ b/.pre-commit-config.yaml
@@ -1,11 +1,11 @@
repos:
- repo: https://github.com/psf/black
- rev: 25.1.0
+ rev: 25.12.0
hooks:
- id: black
- repo: https://github.com/pycqa/isort
- rev: 6.0.1
+ rev: 7.0.0
hooks:
- id: isort
@@ -17,32 +17,32 @@ repos:
files: \.html$
- repo: https://github.com/asottile/pyupgrade
- rev: v3.19.1
+ rev: v3.21.2
hooks:
- id: pyupgrade
- args: [ "--py310-plus" ]
+ args: [ "--py313-plus" ]
- repo: https://github.com/rtts/djhtml
- rev: '3.0.7'
+ rev: '3.0.10'
hooks:
- id: djhtml
- id: djcss
- id: djjs
- repo: https://github.com/adamchainz/django-upgrade
- rev: 1.24.0
+ rev: 1.29.1
hooks:
- id: django-upgrade
- args: [ --target-version, "4.1" ]
+ args: [ --target-version, "6.0" ]
- repo: https://github.com/charliermarsh/ruff-pre-commit
- rev: 'v0.11.3'
+ rev: 'v0.14.10'
hooks:
- id: ruff
args: [--fix, --exit-non-zero-on-fix]
- repo: https://github.com/adamchainz/djade-pre-commit
- rev: '1.3.2'
+ rev: '1.7.0'
hooks:
- id: djade
args: [--target-version, "5.1"]
diff --git a/catalog/management/commands/download_programs.py b/catalog/management/commands/download_programs.py
index 22d29bf8..cae6fd65 100644
--- a/catalog/management/commands/download_programs.py
+++ b/catalog/management/commands/download_programs.py
@@ -71,7 +71,7 @@ def handle(self, *args: Any, **options: Any) -> None:
if mnemonic_span.text not in known_slugs:
fac = mnemonic_span.find_previous_siblings("a")
program_name = mnemonic_span.find_previous(
- "strong", "search-result__structure-intitule"
+ "strong", {"class": "search-result__structure-intitule"}
).text
faculties: list = []
@@ -91,13 +91,13 @@ def handle(self, *args: Any, **options: Any) -> None:
}
if option_div := mnemonic_span.find_previous(
- "div", "search-result__resultat--fille"
+ "div", {"class": "search-result__resultat--fille"}
):
parent_program_div = option_div.find_previous(
- "div", "search-result__result-item"
+ "div", {"class": "search-result__result-item"}
)
parent_mnemonic_span = parent_program_div.find(
- "span", "search-result__mnemonique"
+ "span", {"class": "search-result__mnemonique"}
)
p["parent"] = parent_mnemonic_span.text
parent_programs.add(parent_mnemonic_span.text)
diff --git a/catalog/migrations/0004_alter_coursecategory_unique_together_and_more.py b/catalog/migrations/0004_alter_coursecategory_unique_together_and_more.py
new file mode 100644
index 00000000..7e5f6b76
--- /dev/null
+++ b/catalog/migrations/0004_alter_coursecategory_unique_together_and_more.py
@@ -0,0 +1,63 @@
+# Generated by Django 6.0 on 2025-12-21 20:19
+
+from django.conf import settings
+from django.db import migrations, models
+
+
+class Migration(migrations.Migration):
+
+ dependencies = [
+ ("catalog", "0003_category_is_archive_course_is_archive"),
+ migrations.swappable_dependency(settings.AUTH_USER_MODEL),
+ ]
+
+ operations = [
+ migrations.AlterUniqueTogether(
+ name="coursecategory",
+ unique_together=set(),
+ ),
+ migrations.AlterUniqueTogether(
+ name="courseuserview",
+ unique_together=set(),
+ ),
+ migrations.AlterField(
+ model_name="category",
+ name="id",
+ field=models.BigAutoField(
+ auto_created=True, primary_key=True, serialize=False, verbose_name="ID"
+ ),
+ ),
+ migrations.AlterField(
+ model_name="course",
+ name="id",
+ field=models.BigAutoField(
+ auto_created=True, primary_key=True, serialize=False, verbose_name="ID"
+ ),
+ ),
+ migrations.AlterField(
+ model_name="coursecategory",
+ name="id",
+ field=models.BigAutoField(
+ auto_created=True, primary_key=True, serialize=False, verbose_name="ID"
+ ),
+ ),
+ migrations.AlterField(
+ model_name="courseuserview",
+ name="id",
+ field=models.BigAutoField(
+ auto_created=True, primary_key=True, serialize=False, verbose_name="ID"
+ ),
+ ),
+ migrations.AddConstraint(
+ model_name="coursecategory",
+ constraint=models.UniqueConstraint(
+ fields=("course", "category"), name="unique_course_category"
+ ),
+ ),
+ migrations.AddConstraint(
+ model_name="courseuserview",
+ constraint=models.UniqueConstraint(
+ fields=("user", "course"), name="unique_user_course_view"
+ ),
+ ),
+ ]
diff --git a/catalog/models.py b/catalog/models.py
index 05f4714b..de944e22 100644
--- a/catalog/models.py
+++ b/catalog/models.py
@@ -108,7 +108,7 @@ class Course(models.Model):
description = models.TextField(default="")
period = models.CharField(
max_length=4,
- choices=PeriodType.choices,
+ choices=PeriodType,
default=PeriodType.UNKNOWN,
)
@@ -142,7 +142,11 @@ class CourseCategory(models.Model):
mandatory = models.BooleanField(default=True)
class Meta:
- unique_together = ("course", "category")
+ constraints = [
+ models.UniqueConstraint(
+ fields=["course", "category"], name="unique_course_category"
+ ),
+ ]
class CourseUserView(models.Model):
@@ -152,7 +156,11 @@ class CourseUserView(models.Model):
last_view = models.DateTimeField(auto_now=True)
class Meta:
- unique_together = ("user", "course")
+ constraints = [
+ models.UniqueConstraint(
+ fields=["user", "course"], name="unique_user_course_view"
+ ),
+ ]
@classmethod
def visit(cls, user, course: Course):
diff --git a/catalog/suggestions.py b/catalog/suggestions.py
index 5c25811a..e1897ffd 100644
--- a/catalog/suggestions.py
+++ b/catalog/suggestions.py
@@ -8,7 +8,7 @@
def distance(v1: list[bool], v2: list[bool]) -> float:
- absolute_difference = [abs(c1 - c2) for c1, c2 in zip(v1, v2)]
+ absolute_difference = [abs(c1 - c2) for c1, c2 in zip(v1, v2, strict=True)]
distance = sum(absolute_difference)
return distance
diff --git a/documents/migrations/0005_alter_vote_unique_together_alter_bulkdocuments_id_and_more.py b/documents/migrations/0005_alter_vote_unique_together_alter_bulkdocuments_id_and_more.py
new file mode 100644
index 00000000..ba5a1e01
--- /dev/null
+++ b/documents/migrations/0005_alter_vote_unique_together_alter_bulkdocuments_id_and_more.py
@@ -0,0 +1,58 @@
+# Generated by Django 6.0 on 2025-12-21 20:19
+
+from django.conf import settings
+from django.db import migrations, models
+
+
+class Migration(migrations.Migration):
+
+ dependencies = [
+ ("documents", "0004_document_thumbnail"),
+ migrations.swappable_dependency(settings.AUTH_USER_MODEL),
+ ]
+
+ operations = [
+ migrations.AlterUniqueTogether(
+ name="vote",
+ unique_together=set(),
+ ),
+ migrations.AlterField(
+ model_name="bulkdocuments",
+ name="id",
+ field=models.BigAutoField(
+ auto_created=True, primary_key=True, serialize=False, verbose_name="ID"
+ ),
+ ),
+ migrations.AlterField(
+ model_name="document",
+ name="id",
+ field=models.BigAutoField(
+ auto_created=True, primary_key=True, serialize=False, verbose_name="ID"
+ ),
+ ),
+ migrations.AlterField(
+ model_name="document",
+ name="thumbnail",
+ field=models.FileField(blank=True, default="", upload_to="thumbnail"),
+ ),
+ migrations.AlterField(
+ model_name="documenterror",
+ name="id",
+ field=models.BigAutoField(
+ auto_created=True, primary_key=True, serialize=False, verbose_name="ID"
+ ),
+ ),
+ migrations.AlterField(
+ model_name="vote",
+ name="id",
+ field=models.BigAutoField(
+ auto_created=True, primary_key=True, serialize=False, verbose_name="ID"
+ ),
+ ),
+ migrations.AddConstraint(
+ model_name="vote",
+ constraint=models.UniqueConstraint(
+ fields=("user", "document"), name="unique_user_document_vote"
+ ),
+ ),
+ ]
diff --git a/documents/models.py b/documents/models.py
index a9763586..e0d26968 100644
--- a/documents/models.py
+++ b/documents/models.py
@@ -52,7 +52,7 @@ class DocumentState(models.TextChoices):
file_type = models.CharField(max_length=255, default="")
original = models.FileField(upload_to="original_document")
pdf = models.FileField(upload_to="pdf_document")
- thumbnail = models.FileField(upload_to="thumbnail", null=True)
+ thumbnail = models.FileField(upload_to="thumbnail", blank=True, default="")
state = models.CharField(
max_length=20,
@@ -179,7 +179,11 @@ class VoteType(models.TextChoices):
vote_type = models.CharField(max_length=10, choices=VoteType.choices)
class Meta:
- unique_together = ("user", "document")
+ constraints = [
+ models.UniqueConstraint(
+ fields=["user", "document"], name="unique_user_document_vote"
+ ),
+ ]
class DocumentError(models.Model):
diff --git a/documents/tasks.py b/documents/tasks.py
index 3bf36ca5..6178fb70 100644
--- a/documents/tasks.py
+++ b/documents/tasks.py
@@ -219,7 +219,7 @@ def repair(self, document_id: int) -> int:
):
try:
subprocess.check_output(
- ["mutool", "clean", "-gggg", "-l", tmpfile.name, output_path],
+ ["mutool", "clean", "-gggg", tmpfile.name, output_path],
stderr=subprocess.STDOUT,
)
except OSError as e:
diff --git a/documents/templates/documents/document_edit.html b/documents/templates/documents/document_edit.html
index abcb7e85..daa22930 100644
--- a/documents/templates/documents/document_edit.html
+++ b/documents/templates/documents/document_edit.html
@@ -3,7 +3,7 @@
{% block title %}Éditer {{ doc.name }}{% endblock %}
{% block head %}
-
{% endblock head %}
diff --git a/documents/templates/documents/document_upload.html b/documents/templates/documents/document_upload.html
index d34d52b3..de61994c 100644
--- a/documents/templates/documents/document_upload.html
+++ b/documents/templates/documents/document_upload.html
@@ -3,7 +3,7 @@
{% block title %}Ajouter un document à {{ course.slug|upper }}{% endblock %}
{% block head %}
-