diff mbox series

[error-report-web,5/5] Add a ruff lint job to CI and fix its findings.

Message ID 20261018014510.72203-11-tim.orling@konsulko.com
State New
Headers show
Series Add GitHub Actions CI and run tests with Docker | expand

Commit Message

Tim Orling Oct. 18, 2026, 1:44 a.m. UTC
Pin ruff and select its classic rules, which find bugs; newer defaults
are mostly style. Fix the findings. The paginator now catches
InvalidPage, and the JSON parser Exception, so deeply nested JSON
(RecursionError) is still reported as invalid. Test bad page numbers.

AI-Generated: Claude Opus 5.5
Signed-off-by: Tim Orling <tim.orling@konsulko.com>
---
 .github/workflows/ci.yml         |  9 +++++++++
 Post/createStatistics.py         |  6 ++----
 Post/models.py                   |  4 +---
 Post/parser.py                   |  5 +++--
 Post/purge.py                    |  2 +-
 Post/templatetags/projecttags.py |  4 ----
 Post/test.py                     | 13 ++++++++++++-
 Post/views.py                    | 10 ++++------
 ruff.toml                        |  5 +++++
 test-data/test-send-error.py     |  4 +++-
 10 files changed, 40 insertions(+), 22 deletions(-)
 create mode 100644 ruff.toml
diff mbox series

Patch

diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml
index 74405ac..f53ae69 100644
--- a/.github/workflows/ci.yml
+++ b/.github/workflows/ci.yml
@@ -20,3 +20,12 @@  jobs:
 
       - name: Build image and run tests
         run: docker/run-tests.sh
+
+  lint:
+    runs-on: ubuntu-latest
+    timeout-minutes: 10
+    steps:
+      - uses: actions/checkout@v5
+
+      - name: Ruff
+        run: pipx run ruff==0.17.0 check --output-format=github .
diff --git a/Post/createStatistics.py b/Post/createStatistics.py
index 09d098e..6ecab0a 100644
--- a/Post/createStatistics.py
+++ b/Post/createStatistics.py
@@ -8,11 +8,9 @@ 
 #
 # Licensed under the MIT license, see COPYING.MIT for details
 
-import sys, os
 from Post.models import Build, BuildFailure
 from django.db.models import Count
-import re
-from datetime import datetime, timedelta
+from datetime import timedelta
 from django import utils
 
 class Statistics:
@@ -52,7 +50,7 @@  class Statistics:
         elif string == "NATIVELSBSTRING":
             errors = Build.objects.filter(DATE__range=[enddate, startdate]).values('NATIVELSBSTRING').annotate(dcount=Count('NATIVELSBSTRING')).order_by('-dcount')[:6]
             items = list(errors)
-            return items;
+            return items
         elif string == "TARGET_SYS":
             errors = Build.objects.filter(DATE__range=[enddate, startdate]).values('TARGET_SYS').annotate(dcount=Count('TARGET_SYS')).order_by('-dcount')[:6]
             items = list(errors)
diff --git a/Post/models.py b/Post/models.py
index 541f394..eef0c0c 100644
--- a/Post/models.py
+++ b/Post/models.py
@@ -7,9 +7,7 @@ 
 # Licensed under the MIT license, see COPYING.MIT for details
 
 from django.db import models
-from django.db.models.signals import post_save
 from django.conf import settings
-from datetime import datetime
 
 import Levenshtein
 
@@ -117,7 +115,7 @@  class BuildFailure(models.Model):
 
         recalc_lev_distance = kwargs.pop('recalc_lev_distance', False)
 
-        if self.LEV_DISTANCE == None or recalc_lev_distance:
+        if self.LEV_DISTANCE is None or recalc_lev_distance:
             self.LEV_DISTANCE = self.calc_lev_distance()
 
         super(BuildFailure, self).save(*args, **kwargs)
diff --git a/Post/parser.py b/Post/parser.py
index b6740d0..092ce24 100644
--- a/Post/parser.py
+++ b/Post/parser.py
@@ -8,7 +8,8 @@ 
 #
 # Licensed under the MIT license, see COPYING.MIT for details
 
-import json, re
+import json
+import re
 import bleach
 from Post.models import Build, BuildFailure, ErrorType
 from Post.validators import clean_link_back
@@ -26,7 +27,7 @@  class Parser:
 
         try:
             jsondata = json.loads(self.data)
-        except:
+        except Exception:
              return  { 'error' : 'Invalid json' }
 
         # Bleach data going directly into the database so that
diff --git a/Post/purge.py b/Post/purge.py
index f4989fb..eb2ee7b 100644
--- a/Post/purge.py
+++ b/Post/purge.py
@@ -1,4 +1,4 @@ 
-from datetime import datetime, timedelta
+from datetime import timedelta
 from django.utils import timezone
 import os
 import sys
diff --git a/Post/templatetags/projecttags.py b/Post/templatetags/projecttags.py
index a01989f..838b8f7 100644
--- a/Post/templatetags/projecttags.py
+++ b/Post/templatetags/projecttags.py
@@ -1,8 +1,4 @@ 
-from datetime import datetime, timedelta
-import re
 from django import template
-from django.utils import timezone
-from django.template.defaultfilters import filesizeformat
 from Post.validators import clean_link_back
 
 register = template.Library()
diff --git a/Post/test.py b/Post/test.py
index 9527a9f..2a98bfc 100755
--- a/Post/test.py
+++ b/Post/test.py
@@ -1,4 +1,6 @@ 
-import urllib.request, urllib.parse, urllib.error
+import urllib.request
+import urllib.parse
+import urllib.error
 import json
 from unittest.mock import patch
 from django.core.management import call_command
@@ -389,6 +391,15 @@  class LinkBackSubmissionTest(TestCase):
 
 
 
+@override_settings(ALLOWED_HOSTS=["testhost"])
+class PaginationTest(TestCase):
+    def test_invalid_page_shows_last_page(self):
+        client = Client(HTTP_HOST="testhost")
+        for page in ("999", "abc"):
+            response = client.get("/Errors/Latest/", {"page": page})
+            self.assertEqual(response.status_code, 200)
+
+
 @patch("Post.management.commands.culldb.time.sleep")
 class CullDbTest(TestCase):
     def setUp(self):
diff --git a/Post/views.py b/Post/views.py
index add68d5..9b6656d 100644
--- a/Post/views.py
+++ b/Post/views.py
@@ -10,19 +10,17 @@ 
 # vi: tabstop=8 expandtab shiftwidth=4 softtabstop=4
 
 from __future__ import division
-from django.shortcuts import get_object_or_404
 from django.shortcuts import HttpResponse, render
 from django.views.decorators.csrf import csrf_exempt
 from django.shortcuts import redirect
-from Post.models import BuildFailure, Build, ErrorType
+from Post.models import BuildFailure, ErrorType
 from Post.parser import Parser
 from django.conf import settings
 from Post.createStatistics import Statistics
-from django.core.paginator import Paginator, EmptyPage
+from django.core.paginator import InvalidPage, Paginator
 from django.core.exceptions import FieldError, ObjectDoesNotExist, RequestDataTooBig
 from django.http import JsonResponse
 from django.db.models import Q
-import json
 import re
 import urllib
 from urllib.parse import urlparse
@@ -76,7 +74,7 @@  def addData(request, return_json=False):
         if return_json:
             response = JsonResponse(result)
         else:
-            if not 'error' in result:
+            if 'error' not in result:
               response = HttpResponse("Your entry can be found here: "+result['build_url'])
             else:
               response = HttpResponse(result['error'])
@@ -252,7 +250,7 @@  def search(request, mode=results_mode.LATEST, **kwargs):
 
     try:
         build_failures = build_failures.page(page)
-    except:
+    except InvalidPage:
         build_failures = build_failures.page(build_failures.num_pages)
 
     context['build_failures'] = build_failures
diff --git a/ruff.toml b/ruff.toml
new file mode 100644
index 0000000..cd9662d
--- /dev/null
+++ b/ruff.toml
@@ -0,0 +1,5 @@ 
+# SPDX-License-Identifier: MIT
+
+[lint]
+# Ruff's classic defaults: bugs, not style.
+select = ["E4", "E7", "E9", "F"]
diff --git a/test-data/test-send-error.py b/test-data/test-send-error.py
index de2fc49..7a8067f 100755
--- a/test-data/test-send-error.py
+++ b/test-data/test-send-error.py
@@ -3,7 +3,9 @@ 
 
 # test/example script for sending data to error-report-web
 
-import urllib.request, urllib.error, urllib.parse
+import urllib.request
+import urllib.error
+import urllib.parse
 import sys
 
 def send_data (url, data_file):