Project

General

Profile

Bug #38706

py3: format des timestamps incorrects dans /api/forms/<slug>/list/

Added by Valentin Deniaud almost 5 years ago. Updated almost 5 years ago.

Status:
Fermé
Priority:
Normal
Target version:
-
Start date:
24 December 2019
Due date:
% Done:

0%

Estimated time:
Patch proposed:
Yes
Planning:
No

Description

En python2 :

{
    "id": 1,
    "url": "https://wcs.dev.publik.love/<slug>/22/",
    "last_update_time": "2019-12-12T13:20:24Z",
    "receipt_time": "2019-12-04T14:57:07Z",
}

En python3 :

{
    "id": 1,
    "url": "https://wcs.dev.publik.love/<slug>/22/",
    "last_update_time": [
        2019,
        12,
        12,
        ...
    ],
    "receipt_time": [
        2019,
        12,
        4,
        ...
    ],
}

Dans backoffice/management.py :

1845             output = [{'id': filled.id,
1846                 'url': filled.get_url(),
1847                 'receipt_time': filled.receipt_time,
1848                 'last_update_time': filled.last_update_time} for filled in items]
1849         return json.dumps(output,
1850                 cls=misc.JSONEncoder)

receipt_time est un time.struct_time. Or quand on va voir l'encodeur custom :

476 class JSONEncoder(json.JSONEncoder):
477     def default(self, obj):
478         if isinstance(obj, time.struct_time):
479             return datetime.datetime.utcfromtimestamp(time.mktime(obj)).isoformat() + 'Z'

La ligne avec datetime renvoie bien la même chose en py2 et 3.
Le problème c'est en fait que, en py2 :

>>> isinstance(time.gmtime(), tuple)
False

Et en py3 :

>>> isinstance(time.gmtime(), tuple)
True

Donc le json.dumps, qui sait encoder des tuples, ne fait plus appel au default et s'occupe de notre struct_time tout seul comme un grand, pour nous donner une liste à la place de la chaîne de caractères.
Parmi les choses que ça casse, wcs-olap.


Files

Associated revisions

Revision 12bfec67 (diff)
Added by Frédéric Péters almost 5 years ago

misc: convert time.struct_time to datetime objects before json dump (#38706)

History

#1

Updated by Valentin Deniaud almost 5 years ago

  • Subject changed from py3: format des timestamps incorrects dans /forms/<slug>/list/ to py3: format des timestamps incorrects dans /api/forms/<slug>/list/
#2

Updated by Frédéric Péters almost 5 years ago

  • Assignee set to Frédéric Péters

Yep, déjà rencontré à un autre endroit(mais je ne retrouve pas le commit précis dans w.c.s., peut-être était-ce un autre projet.

Ici a priori ce mini-patch devrait tourner. (alternativement faire le .strftime(...) directement) mais c'est quand même plutôt chiant que python 3 offre une sérialisation de base pour time.struct_time qui soit pourrie, et pas nécessairement évidente à changer (vu que ça en fait un type connu et que JSONEncoder::default n'est plus appelée).

-            return datetime.datetime.utcfromtimestamp(time.mktime(obj)).isoformat() + 'Z'
+            obj = datetime.datetime.utcfromtimestamp(time.mktime(obj))
 

(édit: non ça ne suffit pas, le time.struct_time est attrapé avant).

#3

Updated by Frédéric Péters almost 5 years ago

Voilà avec des tests explicites sur le format des dates retournés par l'API et un assert pour assurer via les tests Python 2 que jamais time.struct_time n'est passé à la sérialisation json.

En passant je retire le "Z" final parce que nos heures ne sont pas UTC, et j'ai vérifié wcs-olap, ça utilise isodate.parse_datetime qui ne va pas s'offusquer de l'absence de timezone.

#4

Updated by Valentin Deniaud almost 5 years ago

  • Status changed from Solution proposée to Solution validée
#5

Updated by Frédéric Péters almost 5 years ago

  • Status changed from Solution validée to Résolu (à déployer)
commit 12bfec671f0b053b387a582a6d6762c57de1851e
Author: Frédéric Péters <fpeters@entrouvert.com>
Date:   Wed Dec 25 10:46:13 2019 +0100

    misc: convert time.struct_time to datetime objects before json dump (#38706)
#6

Updated by Frédéric Péters almost 5 years ago

  • Status changed from Résolu (à déployer) to Solution déployée

Also available in: Atom PDF