0001-general-use-lazy-variables-to-generate-inspect-page-.patch
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 |
- |