Projet

Général

Profil

0001-general-use-lazy-variables-to-generate-inspect-page-.patch

Frédéric Péters, 25 février 2020 13:38

Télécharger (12,6 ko)

Voir les différences:

Subject: [PATCH] general: use lazy variables to generate inspect page (#39849)

 tests/test_backoffice_pages.py | 25 ++++++++++++
 wcs/backoffice/management.py   | 40 ++++++++++---------
 wcs/data_sources.py            |  3 ++
 wcs/qommon/substitution.py     | 21 ++++++++++
 wcs/variables.py               | 70 +++++++++++++++++++++++++++++-----
 wcs/wf/create_formdata.py      |  5 +++
 6 files changed, 135 insertions(+), 29 deletions(-)
tests/test_backoffice_pages.py
32 32
from wcs.qommon.form import PicklableUpload
33 33
from wcs.qommon.ident.password_accounts import PasswordAccount
34 34
from wcs.qommon.http_request import HTTPRequest
35
from wcs.qommon.substitution import CompatibilityNamesDict
35 36
from wcs.roles import Role
36 37
from wcs.workflows import (Workflow, CommentableWorkflowStatusItem,
37 38
        ChoiceWorkflowStatusItem, EditableWorkflowStatusItem,
......
5923 5924
    assert pq('.field-type-file .value').text() == 'bar'
5924 5925

  
5925 5926

  
5927
def test_linked_forms_variables(create_formdata):
5928
    # create source formdata
5929
    formdata = create_formdata['source_formdef'].data_class()()
5930
    upload = PicklableUpload('/foo/bar', content_type='text/plain')
5931
    upload.receive([b'hello world'])
5932
    formdata.data = {
5933
        '0': 'coucou',
5934
        '1': upload,
5935
    }
5936
    formdata.just_created()
5937
    formdata.store()
5938
    formdata.perform_workflow()
5939
    formdata.store()
5940
    formdata.jump_status('2')
5941
    formdata.perform_workflow()
5942
    formdata.store()
5943

  
5944
    get_publisher().substitutions.reset()
5945
    get_publisher().substitutions.feed(formdata)
5946
    substvars = get_publisher().substitutions.get_context_variables(mode='lazy')
5947
    assert str(substvars['form_links_resubmitted_form_var_foo_string']) == 'coucou'
5948
    assert 'form_links_resubmitted_form_var_foo_string' in substvars.get_flat_keys()
5949

  
5950

  
5926 5951
def test_backoffice_create_formdata_map_fields_by_varname(create_formdata):
5927 5952
    create_formdata['create_formdata'].map_fields_by_varname = True
5928 5953
    create_formdata['create_formdata'].mappings  = []
wcs/backoffice/management.py
19 19
import json
20 20
import re
21 21
import time
22
import types
22 23
import vobject
23 24

  
24 25
try:
......
44 45
from ..qommon.evalutils import make_datetime
45 46
from ..qommon.misc import C_, ellipsize
46 47
from ..qommon.afterjobs import AfterJob
48
from ..qommon.substitution import CompatibilityNamesDict
47 49
from ..qommon import emails
48 50
from ..qommon import sms
49 51
from ..qommon import errors
......
62 64
from wcs.formdata import FormData
63 65
from wcs.formdef import FormDef
64 66
from wcs.roles import logged_users_role, Role
67
from wcs.variables import LazyFieldVar
65 68
from wcs.workflows import get_role_translation, template_on_formdata
66 69

  
67 70
from .submission import FormFillPage
......
2619 2622
        r += htmltext('<div id="inspect-variables" class="section">')
2620 2623
        r += htmltext('<h2>%s</h2>') % _('Variables')
2621 2624
        r += htmltext('<ul class="form-inspector biglist">')
2622
        substvars = self.filled.get_static_substitution_variables()
2623
        substvars.update(self.filled.formdef.get_static_substitution_variables())
2625

  
2626
        substvars = CompatibilityNamesDict()
2627
        substvars.update(self.filled.get_substitution_variables())
2628
        static_substvars = {}
2624 2629

  
2625 2630
        def safe(v):
2626 2631
            if isinstance(v, str):
......
2635 2640
                    v = repr(v)
2636 2641
            return v
2637 2642

  
2638
        backward_compatibility_varnames = re.compile('^(attachments|form_field_.*|'
2639
                                                 'form_f[0-9]+|form_fbo[0-9]+|form_user_f[0-9]+|'
2640
                                                 'form_f[a-f0-9]{8}_.*|'
2641
                                                 'form_fbo[a-f0-9]{8}_.*|'
2642
                                                 'form_user_f[a-f0-9]{8}_.*|'
2643
                                                 'form_user_field_.*|form_user_f_.*)$')
2644
        blacklisted_varnames = ['form_objects']
2645

  
2646
        for k, v in sorted(substvars.items()):
2647
            if k in blacklisted_varnames:
2643
        for k in sorted(substvars.get_flat_keys()):
2644
            k = safe(k)
2645
            v = substvars[k]
2646
            if isinstance(v, LazyFieldVar):
2647
                r += htmltext('<li><code title="%s">%s</code>') % (k, k)
2648
                r += htmltext('  <div class="value"><span>%s</span>') % v
2649
            elif isinstance(v, (types.FunctionType, types.MethodType)):
2648 2650
                continue
2649
            if backward_compatibility_varnames.search(k):
2651
            elif hasattr(v, 'inspect_keys') or isinstance(v, dict):
2652
                # skip expanded
2650 2653
                continue
2651

  
2652
            k = safe(k)
2653
            r += htmltext('<li><code title="%s">%s</code>') % (k, k)
2654
            r += htmltext('  <div class="value"><span>%s</span>') % ellipsize(safe(v), 10000)
2655
            if not isinstance(v, six.string_types):
2656
                r += htmltext(' <span class="type">(%r)</span>') % type(v)
2654
            else:
2655
                r += htmltext('<li><code title="%s">%s</code>') % (k, k)
2656
                r += htmltext('  <div class="value"><span>%s</span>') % ellipsize(safe(v), 10000)
2657
                if not isinstance(v, six.string_types):
2658
                    r += htmltext(' <span class="type">(%r)</span>') % type(v)
2657 2659
            r += htmltext('</div></li>')
2658 2660
        r += htmltext('</div>')
2659 2661

  
wcs/data_sources.py
451 451
class DataSourcesSubstitutionProxy(object):
452 452
    def __getattr__(self, attr):
453 453
        return get_structured_items(NamedDataSource.get_by_slug(attr).data_source)
454

  
455
    def inspect_keys(self):
456
        return []
wcs/qommon/substitution.py
154 154
        except KeyError:
155 155
            return default
156 156

  
157
    def get_flat_keys(self):
158
        flat_keys = {}
159

  
160
        def flatten(base, depth=10):
161
            item = self[base]
162
            if hasattr(item, 'inspect_keys'):
163
                sub_keys = item.inspect_keys()
164
            elif isinstance(item, dict):
165
                sub_keys = item.keys()
166
            else:
167
                return
168
            for sub_key in sub_keys:
169
                new_base = '%s_%s' % (base, sub_key)
170
                flat_keys[new_base] = None
171
                flatten(new_base, depth=depth - 1)
172

  
173
        for key in self.keys():
174
            flatten(key)
175

  
176
        return flat_keys.keys()
177

  
157 178
    def __getitem__(self, key):
158 179
        try:
159 180
            val = super(CompatibilityNamesDict, self).__getitem__(key)
wcs/variables.py
168 168
    def __init__(self, formdef):
169 169
        self._formdef = formdef
170 170

  
171
    def inspect_keys(self):
172
        return self.options.keys()
173

  
171 174
    _options = None
172 175
    @property
173 176
    def options(self):
......
202 205
        super(LazyFormData, self).__init__(formdata.formdef)
203 206
        self._formdata = formdata
204 207

  
208
    def inspect_keys(self):
209
        blacklist = ('field', 'inspect_keys', 'page_no', 'role', 'formdef', 'objects')
210
        for key in dir(self):
211
            if key[0] == '_' or key in blacklist:
212
                continue
213
            yield key
214

  
205 215
    @property
206 216
    def objects(self):
207 217
        return LazyFormDefObjectsManager(self._formdef, formdata=self._formdata)
......
442 452
        self._data = data or {}
443 453
        self._formdata = formdata
444 454

  
455
    def inspect_keys(self):
456
        return self.varnames.keys()
457

  
445 458
    _varnames = None
446 459
    @property
447 460
    def varnames(self):
......
488 501
            return LazyFieldVarMap(self._data, field, self._formdata)
489 502
        if field.key == 'password':
490 503
            return LazyFieldVarPassword(self._data, field, self._formdata)
504
        if field.store_structured_value:
505
            return LazyFieldVarStructured(self._data, field, self._formdata)
491 506

  
492 507
        return LazyFieldVar(self._data, field, self._formdata)
493 508

  
......
560 575
            return getattr(self, key)
561 576
        except AttributeError:
562 577
            pass
563
        structured_value = self._field.get_structured_value(self._data)
564
        if not structured_value:
565
            raise KeyError(key)
566
        if isinstance(structured_value, dict):
567
            return structured_value[key]
568
        if isinstance(structured_value, list):
569
            for i, struct_value in enumerate(structured_value):
570
                if str(key) == str(i):
571
                    return struct_value
572 578
        raise KeyError(key)
573 579

  
574 580
    def __iter__(self):
......
590 596
        raise AssertionError('lazy cannot be pickled')
591 597

  
592 598

  
599
class LazyFieldVarStructured(LazyFieldVar):
600
    def inspect_keys(self):
601
        structured_value = self._field.get_structured_value(self._data)
602
        if not structured_value:
603
            return []
604

  
605
        keys = ['raw']
606

  
607
        def walk(base, value):
608
            if isinstance(value, dict):
609
                for k, v in value.items():
610
                    walk(k if not base else base + '_' + k, v)
611
            else:
612
                keys.append(base)
613

  
614
        walk('', structured_value)
615
        return keys
616

  
617
    def __getitem__(self, key):
618
        try:
619
            return super(LazyFieldVarStructured, self).__getitem__(key)
620
        except KeyError:
621
            pass
622
        structured_value = self._field.get_structured_value(self._data)
623
        if not structured_value:
624
            raise KeyError(key)
625
        if isinstance(structured_value, dict):
626
            return structured_value[key]
627
        if isinstance(structured_value, list):
628
            for i, struct_value in enumerate(structured_value):
629
                if str(key) == str(i):
630
                    return struct_value
631
        raise KeyError(key)
632

  
633

  
593 634
class DateOperatorsMixin(object):
594 635
    def __eq__(self, other):
595 636
        if hasattr(other, 'timetuple'):
......
643 684

  
644 685

  
645 686
class LazyFieldVarDate(DateOperatorsMixin, LazyFieldVar):
687
    def inspect_keys(self):
688
        return ['year', 'month', 'day']
689

  
646 690
    def get_raw(self):
647 691
        return self._data.get(self._field.id)
648 692

  
......
688 732
    day = tm_mday
689 733

  
690 734

  
691
class LazyFieldVarMap(LazyFieldVar):
735
class LazyFieldVarMap(LazyFieldVarStructured):
692 736
    def split(self, *args, **kwargs):
693 737
        # Compatibility with usage of map variable as a string. It is
694 738
        # recommended to use lat/lon properties instead.
695 739
        return self._data.get(self._field.id).split(*args, **kwargs)
696 740

  
741
    def inspect_keys(self):
742
        return ['lat', 'lon']
743

  
697 744

  
698 745
class LazyFieldVarPassword(LazyFieldVar):
699 746
    def __getitem__(self, key):
......
708 755
    def __init__(self, user):
709 756
        self._user = user
710 757

  
758
    def inspect_keys(self):
759
        return ['display_name', 'email', 'var']
760

  
711 761
    @property
712 762
    def display_name(self):
713 763
        return self._user.display_name
wcs/wf/create_formdata.py
177 177
                return part.formdata.get_substitution_variables()
178 178
        raise AttributeError(varname)
179 179

  
180
    def inspect_keys(self):
181
        for part in self._formdata.iter_evolution_parts():
182
            if isinstance(part, LinkedFormdataEvolutionPart) and part.varname:
183
                yield part.varname
184

  
180 185

  
181 186
class CreateFormdataWorkflowStatusItem(WorkflowStatusItem):
182 187
    description = N_('New Form Creation')
183
-