Skip to content

Commit

Permalink
The reconsider and need modifiers were not active on all mandatory bl…
Browse files Browse the repository at this point in the history
…ocks; the depends on and on change features did not work on all code blocks executed during the processing of actions; when playground examples is an empty list, the Playground did not omit showing the Examples section.
  • Loading branch information
jhpyle committed Jan 17, 2024
1 parent d6cd734 commit 21d5407
Show file tree
Hide file tree
Showing 4 changed files with 66 additions and 4 deletions.
10 changes: 10 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,15 @@
# Change Log

## [1.4.92] - 2024-01-17

### Fixed
- The `reconsider` and `need` modifiers were not active on all
`mandatory` blocks.
- The `depends on` and `on change` features did not work on all `code`
blocks executed during `process_action()`.
- Playground raised exception if `playground examples` is an empty
list.

## [1.4.91] - 2024-01-07

### Changed
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ metadata:
short title: Actions
documentation: "https://docassemble.org/docs/functions.html#url_action"
example start: 1
example end: 9
example end: 12
---
mandatory: True
question: Actions
Expand All @@ -19,6 +19,8 @@ subquestion: |
[Variable defined by code](${ url_action('vegetable_asked_about') })
[Variable defined by code and question](${ url_action('legume_rationale') })
[event code](${ url_action('increment_counter') })
[event code that calls force_ask()](${ url_action('review_preferences') })
Expand Down Expand Up @@ -58,6 +60,32 @@ question: |
fields:
- Favorite vegetable: favorite_vegetable
---
question: |
What is your favorite legume?
fields:
- Legume: favorite_legume
---
question: |
Why do you like ${ favorite_legume }?
subquestion: |
Note that `legume_rationale` has already been defined by a
`code` block during this action, but this `question` is
being asked anyway.
An `action` will continue past a `code` block that defines a
variable and will seek a `question` that defines the same
variable, if such a `question` exists.
fields:
- label: |
Reason liking ${ favorite_legume }
field: legume_rationale
label above field: True
input type: area
---
code: |
favorite_legume
legume_rationale = "because legumes are good"
---
event: increment_counter
code: |
counter += 1
Expand Down
20 changes: 18 additions & 2 deletions docassemble_base/docassemble/base/parse.py
Original file line number Diff line number Diff line change
Expand Up @@ -4923,14 +4923,23 @@ def exec_setup(self, is_generic, the_x, iterators, the_user_dict):
if len(iterators) > 0:
for indexno, item in enumerate(iterators):
exec(list_of_indices[indexno] + " = " + item, the_user_dict)
for the_field in self.undefine:
for the_field in [substitute_vars(item, is_generic, the_x, iterators) for item in self.undefine]:
docassemble.base.functions.undefine(the_field)
if len(self.reconsider) > 0:
docassemble.base.functions.reconsider(*[substitute_vars(item, is_generic, the_x, iterators) for item in self.reconsider])
if self.need is not None:
for need_code in self.need:
eval(need_code, the_user_dict)

def exec_setup_mandatory(self, the_user_dict):
for the_field in self.undefine:
docassemble.base.functions.undefine(the_field)
if len(self.reconsider) > 0:
docassemble.base.functions.reconsider(*self.reconsider)
if self.need is not None:
for need_code in self.need:
eval(need_code, the_user_dict)

def recursive_data_from_code(self, target, objects=False, plain=False):
if isinstance(target, dict) or (hasattr(target, 'elements') and isinstance(target.elements, dict)):
new_dict = {}
Expand Down Expand Up @@ -8597,6 +8606,7 @@ def assemble(self, user_dict, interview_status=None, old_user_dict=None, force_q
if self.debug:
interview_status.seeking.append({'question': question, 'reason': 'initial', 'time': time.time()})
docassemble.base.functions.this_thread.current_question = question
question.exec_setup_mandatory(user_dict)
exec_with_trap(question, user_dict)
continue
if question.name and question.name in user_dict['_internal']['answered']:
Expand All @@ -8606,6 +8616,7 @@ def assemble(self, user_dict, interview_status=None, old_user_dict=None, force_q
if question.question_type == "data":
if self.debug:
interview_status.seeking.append({'question': question, 'reason': 'data', 'time': time.time()})
question.exec_setup_mandatory(user_dict)
if isinstance(question.gathered, (bool, NoneType)):
gathered = question.gathered
else:
Expand All @@ -8624,6 +8635,7 @@ def assemble(self, user_dict, interview_status=None, old_user_dict=None, force_q
if question.question_type == "data_from_code":
if self.debug:
interview_status.seeking.append({'question': question, 'reason': 'data', 'time': time.time()})
question.exec_setup_mandatory(user_dict)
if isinstance(question.gathered, (bool, NoneType)):
gathered = question.gathered
else:
Expand All @@ -8642,6 +8654,7 @@ def assemble(self, user_dict, interview_status=None, old_user_dict=None, force_q
if question.question_type == "objects_from_file":
if self.debug:
interview_status.seeking.append({'question': question, 'reason': 'objects from file', 'time': time.time()})
question.exec_setup_mandatory(user_dict)
if isinstance(question.use_objects, (bool, NoneType)):
use_objects = bool(question.use_objects)
else:
Expand All @@ -8657,6 +8670,7 @@ def assemble(self, user_dict, interview_status=None, old_user_dict=None, force_q
interview_status.seeking.append({'question': question, 'reason': 'objects', 'time': time.time()})
# logmessage("Going into objects")
docassemble.base.functions.this_thread.current_question = question
question.exec_setup_mandatory(user_dict)
for keyvalue in question.objects:
for variable in keyvalue:
object_type_name = keyvalue[variable]
Expand All @@ -8677,6 +8691,7 @@ def assemble(self, user_dict, interview_status=None, old_user_dict=None, force_q
# logmessage("Running some code:\n\n" + question.sourcecode)
# logmessage("Question name is " + question.name)
docassemble.base.functions.this_thread.current_question = question
question.exec_setup_mandatory(user_dict)
exec_with_trap(question, user_dict)
# logmessage("Code completed")
if question.name:
Expand All @@ -8691,6 +8706,7 @@ def assemble(self, user_dict, interview_status=None, old_user_dict=None, force_q
interview_status.seeking.append({'question': the_question, 'reason': 'result of multiple choice', 'time': time.time()})
if the_question.question_type in ["code", "event_code"]:
docassemble.base.functions.this_thread.current_question = the_question
question.exec_setup_mandatory(user_dict)
exec_with_trap(the_question, user_dict)
interview_status.mark_tentative_as_answered(user_dict)
continue
Expand Down Expand Up @@ -9485,12 +9501,12 @@ def askfor(self, missingVariable, user_dict, old_user_dict, interview_status, **
eval(missing_var, user_dict)
if was_defined:
exec("del __oldvariable__", user_dict)
question.invalidate_dependencies(user_dict, old_values)
if seeking_question:
continue
# question.mark_as_answered(user_dict)
docassemble.base.functions.pop_current_variable()
docassemble.base.functions.pop_event_stack(origMissingVariable)
question.invalidate_dependencies(user_dict, old_values)
return {'type': 'continue', 'sought': missing_var, 'orig_sought': origMissingVariable}
except:
if was_defined:
Expand Down
10 changes: 9 additions & 1 deletion docassemble_webapp/docassemble/webapp/server.py
Original file line number Diff line number Diff line change
Expand Up @@ -23021,7 +23021,11 @@ def playground_page():
page_title += " / " + playground_user.email
if current_project != 'default':
page_title += " / " + current_project
response = make_response(render_template('pages/playground.html', projects=get_list_of_projects(playground_user.id), current_project=current_project, version_warning=None, bodyclass='daadminbody', use_gd=use_gd, use_od=use_od, userid=playground_user.id, page_title=Markup(page_title), tab_title=word("Playground"), extra_css=Markup('\n <link href="' + url_for('static', filename='app/playgroundbundle.css', v=da_version) + '" rel="stylesheet">'), extra_js=Markup('\n <script src="' + url_for('static', filename="app/playgroundbundle.js", v=da_version) + '"></script>\n ' + kbLoad + cm_setup + '<script>\n var daConsoleMessages = ' + json.dumps(console_messages) + ';\n $("#daDelete").click(function(event){if (originalFileName != $("#playground_name").val() || $("#playground_name").val() == \'\'){ $("#form button[name=\'submit\']").click(); event.preventDefault(); return false; } if(!confirm("' + word("Are you sure that you want to delete this playground file?") + '")){event.preventDefault();}});\n daTextArea = document.getElementById("playground_content");\n var daCodeMirror = CodeMirror.fromTextArea(daTextArea, {specialChars: /[\\u00a0\\u0000-\\u001f\\u007f-\\u009f\\u00ad\\u061c\\u200b-\\u200f\\u2028\\u2029\\ufeff]/, mode: "' + ('yamlmixed' if daconfig.get('test yamlmixed mode') else 'yamlmixed') + '", ' + kbOpt + 'tabSize: 2, tabindex: 70, autofocus: false, lineNumbers: true, matchBrackets: true, lineWrapping: ' + ('true' if daconfig.get('wrap lines in playground', True) else 'false') + '});\n $(window).bind("beforeunload", function(){daCodeMirror.save(); $("#form").trigger("checkform.areYouSure");});\n $("#form").areYouSure(' + json.dumps({'message': word("There are unsaved changes. Are you sure you wish to leave this page?")}) + ');\n $("#form").bind("submit", function(){daCodeMirror.save(); $("#form").trigger("reinitialize.areYouSure"); return true;});\n daCodeMirror.setSize(null, null);\n daCodeMirror.setOption("extraKeys", { Tab: function(cm) { var spaces = Array(cm.getOption("indentUnit") + 1).join(" "); cm.replaceSelection(spaces); }, "Ctrl-Space": "autocomplete", "F11": function(cm) { cm.setOption("fullScreen", !cm.getOption("fullScreen")); }, "Esc": function(cm) { if (cm.getOption("fullScreen")) cm.setOption("fullScreen", false); }});\n daCodeMirror.setOption("coverGutterNextToScrollbar", true);\n' + indent_by(ajax, 6) + '\n exampleData = JSON.parse(atob("' + pg_ex['encoded_data_dict'] + '"));\n activateExample("' + str(pg_ex['pg_first_id'][0]) + '", false);\n $("#my-form").trigger("reinitialize.areYouSure");\n $("#daVariablesReport").on("shown.bs.modal", function () { daFetchVariableReport(); })\n </script>'), form=form, fileform=fileform, files=sorted(files, key=lambda y: y['name'].lower()), any_files=any_files, pulldown_files=sorted(pulldown_files, key=lambda y: y.lower()), current_file=the_file, active_file=active_file, content=content, variables_html=Markup(variables_html), example_html=pg_ex['encoded_example_html'], interview_path=interview_path, is_new=str(is_new), valid_form=str(valid_form), own_playground=bool(playground_user.id == current_user.id)), 200)
extra_js = '<script src="' + url_for('static', filename="app/playgroundbundle.js", v=da_version) + '"></script>\n ' + kbLoad + cm_setup + '<script>\n var daConsoleMessages = ' + json.dumps(console_messages) + ';\n $("#daDelete").click(function(event){if (originalFileName != $("#playground_name").val() || $("#playground_name").val() == \'\'){ $("#form button[name=\'submit\']").click(); event.preventDefault(); return false; } if(!confirm("' + word("Are you sure that you want to delete this playground file?") + '")){event.preventDefault();}});\n daTextArea = document.getElementById("playground_content");\n var daCodeMirror = CodeMirror.fromTextArea(daTextArea, {specialChars: /[\\u00a0\\u0000-\\u001f\\u007f-\\u009f\\u00ad\\u061c\\u200b-\\u200f\\u2028\\u2029\\ufeff]/, mode: "' + ('yamlmixed' if daconfig.get('test yamlmixed mode') else 'yamlmixed') + '", ' + kbOpt + 'tabSize: 2, tabindex: 70, autofocus: false, lineNumbers: true, matchBrackets: true, lineWrapping: ' + ('true' if daconfig.get('wrap lines in playground', True) else 'false') + '});\n $(window).bind("beforeunload", function(){daCodeMirror.save(); $("#form").trigger("checkform.areYouSure");});\n $("#form").areYouSure(' + json.dumps({'message': word("There are unsaved changes. Are you sure you wish to leave this page?")}) + ');\n $("#form").bind("submit", function(){daCodeMirror.save(); $("#form").trigger("reinitialize.areYouSure"); return true;});\n daCodeMirror.setSize(null, null);\n daCodeMirror.setOption("extraKeys", { Tab: function(cm) { var spaces = Array(cm.getOption("indentUnit") + 1).join(" "); cm.replaceSelection(spaces); }, "Ctrl-Space": "autocomplete", "F11": function(cm) { cm.setOption("fullScreen", !cm.getOption("fullScreen")); }, "Esc": function(cm) { if (cm.getOption("fullScreen")) cm.setOption("fullScreen", false); }});\n daCodeMirror.setOption("coverGutterNextToScrollbar", true);\n' + indent_by(ajax, 6) + '\n'
if pg_ex['encoded_data_dict'] is not None:
extra_js += ' exampleData = JSON.parse(atob("' + pg_ex['encoded_data_dict'] + '"));\n activateExample("' + str(pg_ex['pg_first_id'][0]) + '", false);\n'
extra_js += ' $("#my-form").trigger("reinitialize.areYouSure");\n $("#daVariablesReport").on("shown.bs.modal", function () { daFetchVariableReport(); })\n </script>'
response = make_response(render_template('pages/playground.html', projects=get_list_of_projects(playground_user.id), current_project=current_project, version_warning=None, bodyclass='daadminbody', use_gd=use_gd, use_od=use_od, userid=playground_user.id, page_title=Markup(page_title), tab_title=word("Playground"), extra_css=Markup('\n <link href="' + url_for('static', filename='app/playgroundbundle.css', v=da_version) + '" rel="stylesheet">'), extra_js=Markup(extra_js), form=form, fileform=fileform, files=sorted(files, key=lambda y: y['name'].lower()), any_files=any_files, pulldown_files=sorted(pulldown_files, key=lambda y: y.lower()), current_file=the_file, active_file=active_file, content=content, variables_html=Markup(variables_html), example_html=pg_ex['encoded_example_html'], interview_path=interview_path, is_new=str(is_new), valid_form=str(valid_form), own_playground=bool(playground_user.id == current_user.id)), 200)
response.headers['Cache-Control'] = 'no-store, no-cache, must-revalidate, post-check=0, pre-check=0, max-age=0'
return response

Expand Down Expand Up @@ -31593,6 +31597,10 @@ def define_examples():
pg_ex['pg_first_id'] = []
data_dict = {}
make_example_html(get_examples(), pg_ex['pg_first_id'], example_html, data_dict)
if len(data_dict) == 0:
pg_ex['encoded_data_dict'] = None
pg_ex['encoded_example_html'] = ""
return
example_html.append(' </div>')
example_html.append(' <div class="col-md-4 da-example-source-col"><h5 class="mb-1">' + word('Source') + '<a href="#" tabindex="0" class="dabadge btn btn-success da-example-copy">' + word("Insert") + '</a></h5><div id="da-example-source-before" class="dainvisible"></div><div id="da-example-source"></div><div id="da-example-source-after" class="dainvisible"></div><div><a tabindex="0" class="da-example-hider" id="da-show-full-example">' + word("Show context of example") + '</a><a tabindex="0" class="da-example-hider dainvisible" id="da-hide-full-example">' + word("Hide context of example") + '</a></div></div>')
example_html.append(' <div class="col-md-6"><h5 class="mb-1">' + word("Preview") + '<a href="#" target="_blank" class="dabadge btn btn-primary da-example-documentation da-example-hidden" id="da-example-documentation-link">' + word("View documentation") + '</a></h5><a href="#" target="_blank" id="da-example-image-link"><img title=' + json.dumps(word("Click to try this interview")) + ' class="da-example-screenshot" id="da-example-image"></a></div>')
Expand Down

0 comments on commit 21d5407

Please sign in to comment.