Projet

Général

Profil

Bug #31823

Erreur 500 lors de l'import d'un worflow contenant '<item />'

Ajouté par Nicolas Roche il y a environ 5 ans. Mis à jour il y a plus de 4 ans.

Statut:
Fermé
Priorité:
Normal
Assigné à:
Version cible:
-
Début:
28 mars 2019
Echéance:
% réalisé:

0%

Temps estimé:
Patch proposed:
Oui
Planning:
Non

Description

Voici un worflow (exporté d'Arles) qui contient des champs vides ce qui pose problème à l'import
et génère une erreur 500 (Internal Serveur Error).
Tout rentre dans l'ordre une fois que tous les tags '<item />' sont supprimés.

Voici les champs incriminés :

<item>{{form_var_telephone}}</item>
<item />
<item />
...

Et voici la trace de Wcs :

Stack trace (most recent call first):
  File "/home/nroche/src/wcs/wcs/workflows.py", line 825, in init_with_xml
   823             if list(el):
   824                 if type(getattr(self, attribute)) is list:
>  825                     v = [x.text.encode(charset) for x in el]
   826                 elif type(getattr(self, attribute)) is dict:
   827                     v = {}

(Pdb) [x.text for x in el]
['{{form_var_telephone}}', None, None, None, None, None, None]

Cette correction permet de poursuivre l'import :

diff --git a/wcs/workflows.py b/wcs/workflows.py
index d1f6980f..7c3aae25 100644
--- a/wcs/workflows.py
+++ b/wcs/workflows.py
@@ -822,7 +822,7 @@ class XmlSerialisable(object):
                 continue
             if list(el):
                 if type(getattr(self, attribute)) is list:
-                    v = [x.text.encode(charset) for x in el]
+                    v = [x.text.encode(charset) for x in el if x]
                 elif type(getattr(self, attribute)) is dict:
                     v = {}
                     for e in el:


Fichiers

workflow-workflow-agenda-rdv-passeport-et-cni.wcs (24,6 ko) workflow-workflow-agenda-rdv-passeport-et-cni.wcs Nicolas Roche, 28 mars 2019 14:47
Screenshot_2019-08-22 Backoffice de Démarches - Workflow - test SMS.png (19,3 ko) Screenshot_2019-08-22 Backoffice de Démarches - Workflow - test SMS.png Nicolas Roche, 22 août 2019 10:45
0001-sms-remove-empty-sms-addresses-submited-by-admin-pag.patch (2,01 ko) 0001-sms-remove-empty-sms-addresses-submited-by-admin-pag.patch Nicolas Roche, 26 août 2019 12:25
0001-sms-remove-empty-sms-addresses-submited-by-admin-pag.patch (2,42 ko) 0001-sms-remove-empty-sms-addresses-submited-by-admin-pag.patch Nicolas Roche, 26 août 2019 17:43
0001-workflow-ignore-empty-exported-item-on-workflow-impo.patch (877 octets) 0001-workflow-ignore-empty-exported-item-on-workflow-impo.patch Nicolas Roche, 26 août 2019 18:17
0002-sms-remove-empty-sms-addresses-submited-by-admin-pag.patch (1,73 ko) 0002-sms-remove-empty-sms-addresses-submited-by-admin-pag.patch Nicolas Roche, 26 août 2019 18:17
0001-workflow-ignore-empty-items-on-workflow-import-31823.patch (2,23 ko) 0001-workflow-ignore-empty-items-on-workflow-import-31823.patch Nicolas Roche, 27 août 2019 16:57
0002-tests-assert-xml-import-export-works-31823.patch (12,9 ko) 0002-tests-assert-xml-import-export-works-31823.patch Nicolas Roche, 27 août 2019 16:57
0003-workflow-allow-empty-base64-content-to-be-exported-a.patch (1,7 ko) 0003-workflow-allow-empty-base64-content-to-be-exported-a.patch Nicolas Roche, 27 août 2019 16:57
0004-sms-ignore-empty-sms-addresses-submited-by-admin-pag.patch (1,81 ko) 0004-sms-ignore-empty-sms-addresses-submited-by-admin-pag.patch Nicolas Roche, 27 août 2019 16:57
0001-tests-add-full-string-de-serialization-to-import-exp.patch (1,53 ko) 0001-tests-add-full-string-de-serialization-to-import-exp.patch Nicolas Roche, 29 août 2019 16:42
0002-workflow-allow-xml-empty-content-to-be-imported-as-b.patch (1,07 ko) 0002-workflow-allow-xml-empty-content-to-be-imported-as-b.patch Nicolas Roche, 29 août 2019 16:43
0003-workflow-ignore-empty-items-on-workflow-import-31823.patch (1,4 ko) 0003-workflow-ignore-empty-items-on-workflow-import-31823.patch Nicolas Roche, 29 août 2019 16:43
0004-forms-do-not-keep-empty-values-when-parsing-Computed.patch (2,56 ko) 0004-forms-do-not-keep-empty-values-when-parsing-Computed.patch Nicolas Roche, 29 août 2019 16:43

Révisions associées

Révision a86a837b (diff)
Ajouté par Nicolas Roche il y a plus de 4 ans

tests: add full string (de)serialization to import/export tests (#31823)

Révision 7ad20714 (diff)
Ajouté par Nicolas Roche il y a plus de 4 ans

workflow: correctly import empty model file (#31823)

Révision 0cf37e19 (diff)
Ajouté par Nicolas Roche il y a plus de 4 ans

workflow: ignore empty items on workflow import (#31823)

Révision e4a16a37 (diff)
Ajouté par Nicolas Roche il y a plus de 4 ans

forms: do not keep empty values when parsing ComputedExpressionWidget (#31823)

Historique

#1

Mis à jour par Nicolas Roche il y a environ 5 ans

  • Tracker changé de Development à Bug
#2

Mis à jour par Frédéric Péters il y a environ 5 ans

Ok mais il faudrait aussi voir à corriger l'origine qui fait qu'un tel export est produit.

#3

Mis à jour par Nicolas Roche il y a plus de 4 ans

  • Sujet changé de Erreur 500 lors de l'import d'un formulaire contenant '<item />' à Erreur 500 lors de l'import d'un worflow contenant '<item />'
  • Description mis à jour (diff)
  • Assigné à mis à Nicolas Roche

Le worflow est accessible sur la prod d'Arles.

A mon avis, les items vides correspondent aux expéditeurs des SMS : aux champs 'À' vides des actions 'SMS (condition)' des statuts 'Votre rendez-vous de demain' et 'Votre rendez-vous est annulé'.

#4

Mis à jour par Nicolas Roche il y a plus de 4 ans

Je confirme, ici j'ai laissé un champ vide.
A l'export j’obtiens :

<?xml version="1.0" encoding="utf-8"?>
<workflow id="2">
  <name>test SMS</name>
  <roles>
    <role id="_receiver">Destinataire</role>
  </roles><last_modification user_id="57">2019-08-22 10:43:24</last_modification>
  <possible_status>
    <status>
      <id>1</id>
      <name>&#233;tat1</name>
      <colour>FFFFFF</colour>
      <visibility />
      <items>
        <item id="1" type="sendsms">
          <to>
            <item>nicolas</item>
            <item />
          </to>
        </item>
      </items>
    </status>
  </possible_status>
</workflow>

Si je reviens éditer l'action, j'ai un nouveau champ qui s'affiche confirmant que le précédent est vu comme renseigné bien qu'il soit vide.

#5

Mis à jour par Nicolas Roche il y a plus de 4 ans

Pour info, j'arrive à corriger avec cet ajout.
(mais il faut encore que j'essaye d'écrire un test)

wcs/workflows.py::SendSMSWorkflowStatusItem(WorkflowStatusItem):

     def add_parameters_widgets(self, form, parameters, prefix='', formdef=None):
         super(SendSMSWorkflowStatusItem, self).add_parameters_widgets(
                 form, parameters, prefix=prefix, formdef=formdef)
         if 'to' in parameters:
+            self.to = [x for x in self.to if x]
             form.add(WidgetList, '%sto' % prefix, title=_('To'),
                      element_type=ComputedExpressionWidget,
                      value=self.to, add_element_label=_('Add Number'),
                      element_kwargs = {'render_br': False})

#6

Mis à jour par Nicolas Roche il y a plus de 4 ans

Voici une proposition de patch.
Je me doute bien que je passe à côté d'une solution plus générique, mais là je sèche.
Dans le même register, et bien que ce soit un peu hors sujet, j'aurais souhaité ajouter des tests sur l'envoi d'informations via le formulaire. J'ai essayé la syntaxe suivante mais rien ne remonte :

resp.form.fields['to$element0$type'] = 'text'
resp.form.fields['to$element0$value_text'] = '0123456789'
resp.form.fields['body'] = 'my body'

#7

Mis à jour par Frédéric Péters il y a plus de 4 ans

Ton patch n'empêche pas le crash avec le fichier renseigné, si ?

#8

Mis à jour par Nicolas Roche il y a plus de 4 ans

Ok mais il faudrait aussi voir à corriger l'origine qui fait qu'un tel export est produit.

non, en effet j'avais zappé le "aussi".

#10

Mis à jour par Nicolas Roche il y a plus de 4 ans

  • Statut changé de Solution proposée à En cours
#11

Mis à jour par Nicolas Roche il y a plus de 4 ans

Désolé, j'ai accumulé 3 bugs dans ce ticket.
Du coup je précise un peu les patchs si dessous.

  • workflow: ignore empty items on workflow import (#31823)
    Pour importer du XML avec des items vides. Erreur 500 décrite au début du ticket :
    AttributeError: 'NoneType' object has no attribute 'encode'
    
  • tests: assert xml import-export works (#31823)
    Une mise à niveau des tests afin de faire faire en sorte que les autres tests puissent aussi détecter le bug corrigé ci-dessus. (dites-moi si ce patch est de trop)
  • workflow: allow empty base64 content to be exported as xml (#31823)
    En faisant la mise à niveau expliquée ci-dessus, je suis tombé sur un bug similaire à l'import des adresses vides ci-dessus :
    TypeError: a2b_base64() argument 1 must be string or buffer, not None
    
  • sms: ignore empty sms addresses submited by admin page (#31823)
    Pour que lorsque l'on enregistre une action SMS, on n'ait pas des adresses vides qui s'accumulent.
    (patch indépendant des précédents)

Dites-moi si ça reste compréhensible.

#12

Mis à jour par Frédéric Péters il y a plus de 4 ans

tests: assert xml import-export works (#31823)
Une mise à niveau des tests afin de faire faire en sorte que les autres tests puissent aussi détecter le bug corrigé ci-dessus. (dites-moi si ce patch est de trop)

Je n'y comprends rien, j'y vois juste 42 lignes changées pour une fonction renommée sans même voir cette fonction renommée.

#13

Mis à jour par Frédéric Péters il y a plus de 4 ans

sans même voir cette fonction renommée

C'est en fait une nouvelle fonction dans 0001 mais assert_import_export_works s'occupe déjà de l'export/import XML, je ne vois pas le sens de ce changement.

#14

Mis à jour par Frédéric Péters il y a plus de 4 ans

Par rapport à 0004 je pense qu'il ne faut pas faire ça à cet endroit, qu'on veut plutôt de manière générique que les éléments vides d'une liste de widgets (WidgetList) soient ignorés,

--- a/wcs/qommon/form.py
+++ b/wcs/qommon/form.py
@@ -1383,6 +1383,12 @@ class WidgetList(quixote.form.widget.WidgetList):
         r += add_element_widget.render()
         return r.getvalue()

+    def _parse(self, request):
+        super(WidgetList, self)._parse(request)
+        if self.value:
+            self.value = [x for x in self.value if x]
#15

Mis à jour par Nicolas Roche il y a plus de 4 ans

  • Statut changé de Solution proposée à En cours
  • dans 0001

assert_import_export_works s'occupe déjà de l'export/import XML

oui, mais sans aller jusqu'à la sérialisation XML,
or c'est lors du chargement du XML par ElementTree que les chaînes vides sont transformées en None.

  • dans 0002
    j'ai choisi de renommer la fonction parce que la fonction d'origine reste requise pour 3 tests qui vérifient que les id n'ont pas changé.
    • test_export_to_model_action
    • test_global_timeout_trigger
    • test_global_webservice_trigger
  • pour 0004,
    merci pour la correction générique,
    par contre je n'arrive pas à écrire de test pour la mettre en évidence.
    Le test ci-dessous fonctionne avant l'application de la correction.
    def test_widgetlist_widget():
        widget = WidgetList('test', value=['a', 'b', 'c'])
        mock_form_submission(req, widget, {'test$element0': 'value-a', 'test$element1': ''})
        assert widget.parse() == ['value-a', 'c']
    
#16

Mis à jour par Frédéric Péters il y a plus de 4 ans

assert_import_export_works s'occupe déjà de l'export/import XML

oui, mais sans aller jusqu'à la sérialisation XML,
(...)
j'ai choisi de renommer la fonction parce que la fonction d'origine reste requise pour 3 tests qui vérifient que les id n'ont pas changé.

Ok mais je ne vois pas le rapport avec les identifiants, faire :

 def assert_import_export_works(wf, include_id=False):
-    wf2 = Workflow.import_from_xml_tree(wf.export_to_xml(include_id), include_id)
+    wf2 = Workflow.import_from_xml_tree(
+            ET.fromstring(ET.tostring(wf.export_to_xml(include_id))), include_id)
     assert ET.tostring(export_to_indented_xml(wf)) == ET.tostring(export_to_indented_xml(wf2))
     return wf2

(et j'ai compris pourquoi j'étais tout perdu par assert_xml_import_export_works, dans la branche la méthode apparait dans un commit qui suit ceux où elle est utilisée).

Je ne vois pas la nécessité de changer le nom/traiter les choses différemment pour certains tests.

Je ferais,

  • un commit "tests: add full string (de)serialization to import/export tests", avec le diff pointé plus haut, mais également dans tests/test_formdef_import.py,
 def assert_xml_import_export_works(formdef, include_id=False):
-    formdef_xml = formdef.export_to_xml(include_id=include_id)
+    formdef_xml = ET.fromstring(ET.tostring(formdef.export_to_xml(include_id=include_id)))
     formdef2 = FormDef.import_from_xml_tree(formdef_xml, include_id=include_id)
  • un commit sur le bug base64, et un autre sur le bug de ce ticket.
  • un commit enfin genre "forms: do not keep empty values when parsing WidgetList".
#17

Mis à jour par Nicolas Roche il y a plus de 4 ans

Mea-cupla, j'avais effectivement inversé l'ordre des commits.
Idem pour les identifiants, ma faute : j'ai zappé le paramètre include_id=.
Merci pour les indications, ça m'a beaucoup aidé (sinon j'y serais encore).

Pour le dernier patch :
Le job était déjà fait par la superclasse Widget::_parse()

        if isinstance(value, basestring) and value.strip():
            self.value = value
        else:
            self.value = None  # ('' -> None)

mais était annulé ensuite par ComputedExpressionWidget::_parse()
        value_content = self.get('value_%s' % value_type) or ''  # (None -> '')

J'ai laissé mon premier test via les SMS pour faire ceinture et bretelles.

#19

Mis à jour par Frédéric Péters il y a plus de 4 ans

  • Statut changé de Solution proposée à Résolu (à déployer)

J'ai légèrement adapté et poussé,

commit e4a16a37c47b9ab182ea3ad6ffd774046b2a861f
Author: Nicolas ROCHE <nroche@entrouvert.com>
Date:   Thu Aug 29 16:03:53 2019 +0200

    forms: do not keep empty values when parsing ComputedExpressionWidget (#31823)

commit 0cf37e198d4b5cb8f6064fce4968cf479896aead
Author: Nicolas ROCHE <nroche@entrouvert.com>
Date:   Thu Aug 29 11:59:36 2019 +0200

    workflow: ignore empty items on workflow import (#31823)

commit 7ad20714aab1ee09692cb7c66878b2645173cc59
Author: Nicolas ROCHE <nroche@entrouvert.com>
Date:   Thu Aug 29 11:39:09 2019 +0200

    workflow: correctly import empty model file (#31823)

commit a86a837bb44e0febae28d584af3eea54b9997e65
Author: Nicolas ROCHE <nroche@entrouvert.com>
Date:   Thu Aug 29 11:17:50 2019 +0200

    tests: add full string (de)serialization to import/export tests (#31823)
#20

Mis à jour par Frédéric Péters il y a plus de 4 ans

  • Statut changé de Résolu (à déployer) à Solution déployée

Formats disponibles : Atom PDF