Bug #31823
Erreur 500 lors de l'import d'un worflow contenant '<item />'
0%
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
Révisions associées
workflow: correctly import empty model file (#31823)
workflow: ignore empty items on workflow import (#31823)
forms: do not keep empty values when parsing ComputedExpressionWidget (#31823)
Historique
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.
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é'.
Mis à jour par Nicolas Roche il y a plus de 4 ans
- Fichier Screenshot_2019-08-22 Backoffice de Démarches - Workflow - test SMS.png Screenshot_2019-08-22 Backoffice de Démarches - Workflow - test SMS.png ajouté
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>é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.
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})
Mis à jour par Nicolas Roche il y a plus de 4 ans
- Fichier 0001-sms-remove-empty-sms-addresses-submited-by-admin-pag.patch 0001-sms-remove-empty-sms-addresses-submited-by-admin-pag.patch ajouté
- Statut changé de Nouveau à Solution proposée
- Patch proposed changé de Non à Oui
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'
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 ?
Mis à jour par Nicolas Roche il y a plus de 4 ans
- Fichier 0001-sms-remove-empty-sms-addresses-submited-by-admin-pag.patch 0001-sms-remove-empty-sms-addresses-submited-by-admin-pag.patch ajouté
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".
Mis à jour par Nicolas Roche il y a plus de 4 ans
- Fichier 0001-workflow-ignore-empty-exported-item-on-workflow-impo.patch 0001-workflow-ignore-empty-exported-item-on-workflow-impo.patch ajouté
- Fichier 0002-sms-remove-empty-sms-addresses-submited-by-admin-pag.patch 0002-sms-remove-empty-sms-addresses-submited-by-admin-pag.patch ajouté
En fait, pour plus de clarté je préférerai livrer 2 patchs distincts.
Mis à jour par Nicolas Roche il y a plus de 4 ans
- Fichier 0001-workflow-ignore-empty-items-on-workflow-import-31823.patch 0001-workflow-ignore-empty-items-on-workflow-import-31823.patch ajouté
- Fichier 0002-tests-assert-xml-import-export-works-31823.patch 0002-tests-assert-xml-import-export-works-31823.patch ajouté
- Fichier 0003-workflow-allow-empty-base64-content-to-be-exported-a.patch 0003-workflow-allow-empty-base64-content-to-be-exported-a.patch ajouté
- Fichier 0004-sms-ignore-empty-sms-addresses-submited-by-admin-pag.patch 0004-sms-ignore-empty-sms-addresses-submited-by-admin-pag.patch ajouté
- Statut changé de En cours à Solution proposée
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.
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.
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.
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]
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']
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".
Mis à jour par Nicolas Roche il y a plus de 4 ans
- Fichier 0001-tests-add-full-string-de-serialization-to-import-exp.patch 0001-tests-add-full-string-de-serialization-to-import-exp.patch ajouté
- Fichier 0002-workflow-allow-xml-empty-content-to-be-imported-as-b.patch 0002-workflow-allow-xml-empty-content-to-be-imported-as-b.patch ajouté
- Fichier 0003-workflow-ignore-empty-items-on-workflow-import-31823.patch 0003-workflow-ignore-empty-items-on-workflow-import-31823.patch ajouté
- Fichier 0004-forms-do-not-keep-empty-values-when-parsing-Computed.patch 0004-forms-do-not-keep-empty-values-when-parsing-Computed.patch ajouté
- Statut changé de En cours à Solution proposée
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.
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)
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
tests: add full string (de)serialization to import/export tests (#31823)