diff --git a/Changelog.md b/Changelog.md index 8695418416a5d164741a17466256500efb0fe7cb..164633390d327c608b3801e493f3e800612d9988 100644 --- a/Changelog.md +++ b/Changelog.md @@ -1,5 +1,9 @@ # Changelog +## [0.9] - 2025-03-28 +- Add version endpoint +- Fix the encoding issue with the windows clients + ## [0.8] - 2025-03-27 - No change, just a new release diff --git a/sage_validation/file_validator/forms.py b/sage_validation/file_validator/forms.py index ef6e9ec49fccd201adcc9a8ec30a53fbfee2e566..990b83ce708a694f1099d3688b0caf7abc67a771 100644 --- a/sage_validation/file_validator/forms.py +++ b/sage_validation/file_validator/forms.py @@ -76,7 +76,9 @@ class CSVUploadForm(forms.Form): self._validate_file_type(file) # Step 2: Parse file and validate headers - csv_file = file.read().decode("utf-8").splitlines() + raw_data = file.read().decode("utf-8-sig") + normalized_data = raw_data.replace("\r\n", "\n").replace("\r", "\n") + csv_file = normalized_data.splitlines() reader = csv.DictReader(csv_file, delimiter=",") fieldnames = reader.fieldnames if reader.fieldnames is not None else [] self._validate_headers(fieldnames) diff --git a/sage_validation/file_validator/views.py b/sage_validation/file_validator/views.py index 5eb98dddf158d5597bdad04b41b256d7b491aaad..b58807d9b45587e4738eafae91e82ae6ab607dfb 100644 --- a/sage_validation/file_validator/views.py +++ b/sage_validation/file_validator/views.py @@ -1,9 +1,12 @@ """Views for the file_validator app.""" import csv import io +from importlib.metadata import PackageNotFoundError +from importlib.metadata import version as get_version from typing import ClassVar from django.http import HttpRequest, HttpResponse +from django.http.response import JsonResponse from django.shortcuts import render from django.urls import reverse_lazy from django.utils import timezone @@ -23,6 +26,14 @@ def index_view(request: HttpRequest) -> HttpResponse: return render(request, "index.html") +def version_view(_request: HttpRequest) -> JsonResponse: + """Return the module version as JSON.""" + try: + module_version = get_version("sage-validation") + except PackageNotFoundError: + module_version = "unknown" + + return JsonResponse({"module": module_version}) def upload_page_view(request: HttpRequest) -> HttpResponse: """Render the file upload page.""" return render(request, "upload.html") @@ -42,7 +53,7 @@ class CSVUploadAPIView(APIView): csv_file = form.cleaned_data["file"] csv_file.seek(0) - decoded_file = csv_file.read().decode("utf-8").strip() + decoded_file = csv_file.read().decode("utf-8-sig").strip() if not decoded_file: return Response({"status": "error", "message": "Uploaded file is empty."}, diff --git a/sage_validation/urls.py b/sage_validation/urls.py index 1146896db11939a8c6ddc3db541093f717b62166..166c07517b9c45ef329e3373195296b58af0fc52 100644 --- a/sage_validation/urls.py +++ b/sage_validation/urls.py @@ -3,7 +3,7 @@ from django.contrib import admin from django.urls import path from django.urls.conf import include -from sage_validation.file_validator.views import index_view +from sage_validation.file_validator.views import index_view, version_view urlpatterns = [ path("admin/", admin.site.urls), @@ -11,4 +11,5 @@ urlpatterns = [ path("", index_view, name="index"), path("", include("social_django.urls", namespace="social")), path("accounts/", include("sage_validation.accounts.urls")), + path("version/", version_view, name="version"), ] diff --git a/setup.py b/setup.py index e5d2f676c254fce4d6fe1a039af8258ae4c27799..efeb525eb13a3892a42525b211f2f7664fac0fd3 100644 --- a/setup.py +++ b/setup.py @@ -3,7 +3,7 @@ from setuptools import find_packages, setup setup( name="sage-validation", - version="0.8", + version="0.9", packages=find_packages(), include_package_data=True, install_requires=[