Repository: zestedesavoir/zds-site

Issue:
Erreur 500 car temps de lecture vide
Rapporté par Sentry.

https://beta.zestedesavoir.com/tutoriels/822/la-programmation-en-c-moderne/ lève une erreur 500, car le temps de lecture estimé est une chaîne de caractères vide et non un entier. Extrait de la backtrace:
```
TypeError: '>' not supported between instances of 'int' and 'str'
...
File "zds/utils/templatetags/humanize_duration.py", line 17, in humanize_duration
    duration_min = max(duration_min, 0)  # to avoid surprises with modulo operations
```
(c'est dans la route `/tutoriels/{pk}/{slug}/`)

Pour tester, on peut récupérer le tutoriel sur le serveur de prod : https://zestedesavoir.com/tutoriels/822/la-programmation-en-c-moderne/

Ce qu'il faudrait faire : 
- traiter le cas si `duration_min` est une chaîne de caractères (vide)
- comprendre pourquoi `duration_min` est une chaîne de caractères vide dans ce cas et corriger le problème 😃 

Avoir sous les yeux la PR récente qui a modifié l'estimation du temps lecture peut sans doute être utile : https://github.com/zestedesavoir/zds-site/pull/6401




Discussion:

Resolving patch:
diff --git a/zds/tutorialv2/views/display.py b/zds/tutorialv2/views/display.py
--- a/zds/tutorialv2/views/display.py
+++ b/zds/tutorialv2/views/display.py
@@ -155,6 +155,9 @@ def get_context_data(self, **kwargs):
                     * char_count
                     / settings.ZDS_APP["content"]["characters_per_minute"]
                 )
+            else:
+                logger.warning("For unknown reason content with id %s has no char count", self.object.pk)
+                context["reading_time"] = 0
         except ZeroDivisionError as e:
             logger.warning("could not compute reading time: setting characters_per_minute is set to zero (error=%s)", e)
 
diff --git a/zds/utils/templatetags/humanize_duration.py b/zds/utils/templatetags/humanize_duration.py
--- a/zds/utils/templatetags/humanize_duration.py
+++ b/zds/utils/templatetags/humanize_duration.py
@@ -1,8 +1,11 @@
+import logging
+import numbers
 from typing import Tuple, List, Iterator, Iterable
 
 from django import template
 from django.utils.translation import ngettext, gettext as _
 
+logger = logging.getLogger(__file__)
 register = template.Library()
 
 
@@ -14,6 +17,9 @@ def humanize_duration(duration_min: int) -> str:
 
     See the unit tests for examples of results.
     """
+    if not isinstance(duration_min, int):
+        logger.warning("Invalid duration %s", duration_min)
+        return humanize_duration(0)
     duration_min = max(duration_min, 0)  # to avoid surprises with modulo operations
     truncated_value = _truncate_duration(
         duration_min,


Test patch:
diff --git a/zds/utils/tests/tests_humanize_duration.py b/zds/utils/tests/tests_humanize_duration.py
--- a/zds/utils/tests/tests_humanize_duration.py
+++ b/zds/utils/tests/tests_humanize_duration.py
@@ -17,6 +17,7 @@ def test_main(self):
             {"input": 110, "expected": "1 heure et 45 minutes"},
             {"input": 125, "expected": "2 heures"},
             {"input": 155, "expected": "2 heures et 30 minutes"},
+            {"input": "", "expected": "moins d'une minute"},
             {"input": 24 * 60, "expected": "24 heures"},
             {"input": 48 * 60, "expected": "48 heures"},
         ]