Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
18 changes: 9 additions & 9 deletions .pre-commit-config.yaml
Original file line number Diff line number Diff line change
@@ -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

Expand All @@ -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"]
8 changes: 4 additions & 4 deletions catalog/management/commands/download_programs.py
Original file line number Diff line number Diff line change
Expand Up @@ -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 = []
Expand All @@ -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)
Expand Down
Original file line number Diff line number Diff line change
@@ -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"
),
),
]
14 changes: 11 additions & 3 deletions catalog/models.py
Original file line number Diff line number Diff line change
Expand Up @@ -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,
)

Expand Down Expand Up @@ -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):
Expand All @@ -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):
Expand Down
2 changes: 1 addition & 1 deletion catalog/suggestions.py
Original file line number Diff line number Diff line change
Expand Up @@ -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

Expand Down
Original file line number Diff line number Diff line change
@@ -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"
),
),
]
8 changes: 6 additions & 2 deletions documents/models.py
Original file line number Diff line number Diff line change
Expand Up @@ -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,
Expand Down Expand Up @@ -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):
Expand Down
2 changes: 1 addition & 1 deletion documents/tasks.py
Original file line number Diff line number Diff line change
Expand Up @@ -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:
Expand Down
2 changes: 1 addition & 1 deletion documents/templates/documents/document_edit.html
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
{% block title %}Éditer {{ doc.name }}{% endblock %}

{% block head %}
<link href="https://unpkg.com/tom-select@2.3.1/dist/css/tom-select.bootstrap5.min.css"
<link href="https://cdn.jsdelivr.net/npm/tom-select@2.4.3/dist/css/tom-select.bootstrap5.min.css"
rel="stylesheet" crossorigin="anonymous">
{% endblock head %}

Expand Down
2 changes: 1 addition & 1 deletion documents/templates/documents/document_upload.html
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
{% block title %}Ajouter un document à {{ course.slug|upper }}{% endblock %}

{% block head %}
<link href="https://unpkg.com/tom-select@2.3.1/dist/css/tom-select.bootstrap5.min.css"
<link href="https://cdn.jsdelivr.net/npm/tom-select@2.4.3/dist/css/tom-select.bootstrap5.min.css"
rel="stylesheet" crossorigin="anonymous">

<style>
Expand Down
6 changes: 3 additions & 3 deletions documents/tests/thumbnail_test.py
Original file line number Diff line number Diff line change
Expand Up @@ -9,15 +9,15 @@ def test_single_page():

def test_single_page_bytes():
with open("documents/tests/files/1page.pdf", "rb") as fp:
i, img = get_thumbnail(stream=fp)
i, _img = get_thumbnail(stream=fp)
assert i == 0


def test_2page_first_almost_empty_takes_second():
i, img = get_thumbnail("documents/tests/files/2page_first_almost_empty.pdf")
i, _img = get_thumbnail("documents/tests/files/2page_first_almost_empty.pdf")
assert i == 1


def test_all_almost_empty_takes_first():
i, img = get_thumbnail("documents/tests/files/repaired.pdf")
i, _img = get_thumbnail("documents/tests/files/repaired.pdf")
assert i == 0
4 changes: 2 additions & 2 deletions documents/views.py
Original file line number Diff line number Diff line change
Expand Up @@ -181,7 +181,7 @@ def document_reupload(request, pk):

if form.is_valid():
file = request.FILES["file"]
name, extension = os.path.splitext(file.name)
_name, extension = os.path.splitext(file.name)

document.pdf.delete(save=False)
document.original.delete(save=False)
Expand Down Expand Up @@ -238,7 +238,7 @@ def document_show(request, pk):
def document_vote(request, pk):
document = get_object_or_404(Document, pk=pk)

vote, created = Vote.objects.get_or_create(document=document, user=request.user)
vote, _created = Vote.objects.get_or_create(document=document, user=request.user)
if vote.vote_type == request.POST.get("vote_type"):
vote.delete()
else:
Expand Down
2 changes: 1 addition & 1 deletion manage.py
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@
def main():
os.environ.setdefault("DJANGO_SETTINGS_MODULE", "www.settings")
try:
from django.core.management import execute_from_command_line
from django.core.management import execute_from_command_line # noqa: PLC0415
except ImportError as exc:
raise ImportError(
"Couldn't import Django. Are you sure it's installed and "
Expand Down
1 change: 0 additions & 1 deletion moderation/apps.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,5 +2,4 @@


class ModerationConfig(AppConfig):
default_auto_field = "django.db.models.BigAutoField"
name = "moderation"
2 changes: 1 addition & 1 deletion pyproject.toml
Original file line number Diff line number Diff line change
Expand Up @@ -58,6 +58,7 @@ dev = [
"pytest-django>=4.11.1",
"responses>=0.25.7",
"time-machine>=2.16.0",
"ruff>=0.13.1",
]

[tool.pytest.ini_options]
Expand Down Expand Up @@ -86,7 +87,6 @@ select = [
# Never ? "FBT", "D", "COM", "T20", "Q", "ARG", "PD"
ignore = [
"E501", # Line too long
"B905", # Not available <3.10
"PT011", # `pytest.raises(Exception)` is too broad
"SIM108", # Use ternary operator
"SIM105", # Use `contextlib.suppress(Alarm)`
Expand Down
16 changes: 7 additions & 9 deletions static/main.js
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
import _ from 'https://cdn.skypack.dev/lodash';
import _ from 'https://cdn.jsdelivr.net/npm/lodash@4.17.21/+esm';

import {Controller, Application} from 'https://unpkg.com/@hotwired/stimulus@3.2.2?module';
import {Autocomplete} from 'https://cdn.skypack.dev/stimulus-autocomplete';
import tomSelect from 'https://unpkg.com/tom-select@2.3.1?module';
import {Controller, Application} from 'https://cdn.jsdelivr.net/npm/@hotwired/stimulus@3.2.2/+esm';
import {Autocomplete} from 'https://cdn.jsdelivr.net/npm/stimulus-autocomplete@3.1.0/+esm';
import tomSelect from 'https://cdn.jsdelivr.net/npm/tom-select@2.4.3/+esm';

function normalize(s) {
let r = s.toLowerCase();
Expand Down Expand Up @@ -83,10 +83,8 @@ class Search extends Controller {
}
}

import bundledEsModulesPdfjsDist from 'https://unpkg.com/@bundled-es-modules/pdfjs-dist@2.16.106';

let pdfjs = bundledEsModulesPdfjsDist
pdfjs.GlobalWorkerOptions.workerSrc = "https://unpkg.com/@bundled-es-modules/pdfjs-dist@2.16.106/build/pdf.worker.js"
import {getDocument, GlobalWorkerOptions} from 'https://cdn.jsdelivr.net/npm/pdfjs-dist@5.4.449/+esm';
GlobalWorkerOptions.workerSrc = "https://cdn.jsdelivr.net/npm/pdfjs-dist@5.4.449/build/pdf.worker.mjs"


class Viewer extends Controller {
Expand All @@ -100,7 +98,7 @@ class Viewer extends Controller {


async connect() {
let loadingTask = pdfjs.getDocument(this.srcValue);
let loadingTask = getDocument(this.srcValue);

loadingTask.onProgress = async (data) => {
let percent = Math.round(data.loaded / data.total * 100)
Expand Down
Loading