Projet

Général

Profil

0001-snapshots-do-not-fail-on-load-error-51641.patch

Lauréline Guérin, 12 mars 2021 16:25

Télécharger (10,3 ko)

Voir les différences:

Subject: [PATCH] snapshots: do not fail on load error (#51641)

 tests/test_snapshots.py                     | 42 ++++++++++++++++
 wcs/backoffice/snapshots.py                 | 56 ++++++++++++++-------
 wcs/blocks.py                               |  4 +-
 wcs/qommon/xml_storage.py                   |  4 +-
 wcs/snapshots.py                            |  5 +-
 wcs/templates/wcs/backoffice/snapshots.html |  2 +
 6 files changed, 91 insertions(+), 22 deletions(-)
tests/test_snapshots.py
10 10
from wcs.blocks import BlockDef
11 11
from wcs.carddef import CardDef
12 12
from wcs.data_sources import NamedDataSource
13
from wcs.fields import ItemField
13 14
from wcs.formdef import FormDef
14 15
from wcs.qommon.form import UploadedFile
15 16
from wcs.qommon.misc import localstrftime
......
231 232
    assert formdef.url_name == formdef_with_history.url_name
232 233

  
233 234

  
235
def test_form_snapshot_restore_with_import_error(pub):
236
    create_superuser(pub)
237
    create_role()
238
    app = login(get_app(pub))
239

  
240
    formdef = FormDef()
241
    formdef.name = 'testform'
242
    formdef.fields = [ItemField(id='1', label='Test', type='item', data_source={'type': 'unknown'})]
243
    formdef.store()
244
    assert pub.snapshot_class.count() == 1
245
    snapshot = pub.snapshot_class.select_object_history(formdef)[0]
246
    resp = app.get('/backoffice/forms/%s/history/%s/restore' % (formdef.id, snapshot.id))
247
    resp = resp.form.submit('submit')
248
    assert 'Can not restore snapshot (Unknown datasources [unknown])' in resp
249

  
250

  
234 251
def test_block_snapshot_browse(pub, blocks_feature):
235 252
    create_superuser(pub)
236 253
    create_role()
......
376 393
    assert pub.custom_view_class.count() == 0  # custom views are not restore on preview
377 394

  
378 395

  
396
def test_form_snapshot_browse_with_import_error(pub):
397
    create_superuser(pub)
398
    create_role()
399
    app = login(get_app(pub))
400

  
401
    formdef = FormDef()
402
    formdef.name = 'testform'
403
    formdef.fields = [ItemField(id='1', label='Test', type='item', data_source={'type': 'unknown'})]
404
    formdef.store()
405
    assert pub.snapshot_class.count() == 1
406
    snapshot = pub.snapshot_class.select_object_history(formdef)[0]
407
    # no error for missing datasource
408
    resp = app.get('/backoffice/forms/%s/history/%s/view/' % (formdef.id, snapshot.id), status=200)
409

  
410
    # other FormdefImportError
411
    formdef.fields = [ItemField(id='1', label='Test', type='foobar')]
412
    formdef.store()
413
    assert pub.snapshot_class.count() == 2
414
    snapshot = pub.snapshot_class.select_object_history(formdef)[0]
415
    resp = app.get('/backoffice/forms/%s/history/%s/view/' % (formdef.id, snapshot.id), status=302)
416
    assert resp.location == 'http://example.net/backoffice/forms/%s/history/' % formdef.id
417
    resp = resp.follow()
418
    assert 'Can not display snapshot (Unknown field type [foobar])' in resp
419

  
420

  
379 421
def test_workflow_snapshot_browse(pub):
380 422
    create_superuser(pub)
381 423
    create_role()
wcs/backoffice/snapshots.py
14 14
# You should have received a copy of the GNU General Public License
15 15
# along with this program; if not, see <http://www.gnu.org/licenses/>.
16 16

  
17
from quixote import get_publisher, get_response, redirect
17
from quixote import get_publisher, get_response, redirect, get_session
18 18
from quixote.directory import Directory
19 19
from quixote.html import TemplateIO, htmltext
20 20

  
21
from wcs.blocks import BlockDef
22
from wcs.carddef import CardDef
23
from wcs.data_sources import NamedDataSource
24
from wcs.formdef import FormDef, FormdefImportError
25
from wcs.workflows import Workflow
26
from wcs.wscalls import NamedWsCall
21 27
from wcs.qommon import _, errors, misc, template
22 28
from wcs.qommon.backoffice.menu import html_top
23 29
from wcs.qommon.form import Form, RadiobuttonsWidget, StringWidget
24
from wcs.qommon.storage import Equal
25 30

  
26 31

  
27 32
class SnapshotsDirectory(Directory):
......
130 135
            return redirect('..')
131 136

  
132 137
        if form.get_submit() == 'submit':
133
            self.snapshot.restore(as_new=bool(action.parse() == 'as-new'))
134
            return redirect(self.snapshot.instance.get_admin_url())
138
            try:
139
                self.snapshot.restore(as_new=bool(action.parse() == 'as-new'))
140
            except FormdefImportError as e:
141
                reason = _(e.msg) % e.msg_args
142
                if e.details:
143
                    reason += ' [%s]' % e.details
144
                error_msg = _('Can not restore snapshot (%s)') % reason
145
                form.set_error('action', error_msg)
146
            else:
147
                return redirect(self.snapshot.instance.get_admin_url())
135 148

  
136 149
        get_response().breadcrumb.append(('restore', _('Restore')))
137 150
        r = TemplateIO(html=True)
......
141 154

  
142 155
    @property
143 156
    def view(self):
144
        from wcs.blocks import BlockDef
145
        from wcs.carddef import CardDef
146
        from wcs.data_sources import NamedDataSource
147
        from wcs.formdef import FormDef
148
        from wcs.workflows import Workflow
149
        from wcs.wscalls import NamedWsCall
150

  
151 157
        klass = self.snapshot.get_object_class()
158
        self.snapshot._check_datasources = False
159
        try:
160
            instance = self.snapshot.instance
161
        except FormdefImportError as e:
162
            reason = _(e.msg) % e.msg_args
163
            if e.details:
164
                reason += ' [%s]' % e.details
165
            error_msg = _('Can not display snapshot (%s)') % reason
166
            get_session().message = ('error', _(error_msg))
167

  
168
            class RedirectDirectory(Directory):
169
                def _q_lookup(sellf, component):
170
                    return redirect('../../')
171

  
172
            return RedirectDirectory()
173

  
152 174
        if klass is BlockDef:
153 175
            from wcs.admin.blocks import BlockDirectory
154 176

  
155
            return BlockDirectory(section='forms', objectdef=self.snapshot.instance)
177
            return BlockDirectory(section='forms', objectdef=instance)
156 178
        if klass is FormDef:
157 179
            from wcs.admin.forms import FormDefPage
158 180

  
159
            return FormDefPage(component='view', instance=self.snapshot.instance)
181
            return FormDefPage(component='view', instance=instance)
160 182
        if klass is CardDef:
161 183
            from wcs.backoffice.cards import CardDefPage
162 184

  
163
            return CardDefPage(component='view', instance=self.snapshot.instance)
185
            return CardDefPage(component='view', instance=instance)
164 186
        if klass is Workflow:
165 187
            from wcs.admin.workflows import WorkflowPage
166 188

  
167
            return WorkflowPage(component='view', instance=self.snapshot.instance)
189
            return WorkflowPage(component='view', instance=instance)
168 190
        if klass is NamedDataSource:
169 191
            from wcs.admin.data_sources import NamedDataSourcePage
170 192

  
171
            return NamedDataSourcePage(component='view', instance=self.snapshot.instance)
193
            return NamedDataSourcePage(component='view', instance=instance)
172 194
        if klass is NamedWsCall:
173 195
            from wcs.admin.wscalls import NamedWsCallPage
174 196

  
175
            return NamedWsCallPage(component='view', instance=self.snapshot.instance)
197
            return NamedWsCallPage(component='view', instance=instance)
wcs/blocks.py
116 116
    def import_from_xml(cls, fd, include_id=False, check_datasources=True):
117 117
        try:
118 118
            tree = ET.parse(fd)
119
        except:
119
        except Exception:
120 120
            raise ValueError()
121 121
        blockdef = cls.import_from_xml_tree(tree, include_id=include_id)
122 122

  
......
144 144
        return blockdef
145 145

  
146 146
    @classmethod
147
    def import_from_xml_tree(cls, tree, include_id=False, snapshot=False):
147
    def import_from_xml_tree(cls, tree, include_id=False, **kwargs):
148 148
        charset = 'utf-8'
149 149
        blockdef = cls()
150 150
        if tree.find('name') is None or not tree.find('name').text:
wcs/qommon/xml_storage.py
79 79
    def import_from_xml(cls, fd, charset=None, include_id=False):
80 80
        try:
81 81
            tree = ET.parse(fd)
82
        except:
82
        except Exception:
83 83
            raise ValueError()
84 84
        return cls.import_from_xml_tree(tree, charset=charset, include_id=include_id)
85 85

  
86 86
    @classmethod
87
    def import_from_xml_tree(cls, tree, include_id=False, charset=None, snapshot=False):
87
    def import_from_xml_tree(cls, tree, include_id=False, charset=None, **kwargs):
88 88
        if charset is None:
89 89
            charset = get_publisher().site_charset
90 90
        obj = cls()
wcs/snapshots.py
85 85
        if self._instance is None:
86 86
            tree = ET.fromstring(self.serialization)
87 87
            self._instance = self.get_object_class().import_from_xml_tree(
88
                tree, include_id=True, snapshot=True
88
                tree,
89
                include_id=True,
90
                snapshot=True,
91
                check_datasources=getattr(self, '_check_datasources', True),
89 92
            )
90 93
            self._instance.readonly = True
91 94
            self._instance.snapshot_object = self
wcs/templates/wcs/backoffice/snapshots.html
5 5
<h2>{% trans "History" %}</h2>
6 6
</div>
7 7

  
8
{{ publisher.get_request.session.display_message|safe }}
9

  
8 10
{% with snapshots=view.snapshots %}
9 11
{% if snapshots %}
10 12
<div class="section">
11
-