Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

New feature: live show if #733

Open
wants to merge 3 commits into
base: master
Choose a base branch
from

Conversation

BryceStevenWilley
Copy link
Contributor

@BryceStevenWilley BryceStevenWilley commented Jan 9, 2024

As previewed in slack, this PR introduces a new feature, called live show if. It works like js show if, but it lets users write python expressions as they would in a code block instead. It uses a simple1 JavaScript to python transpiler to convert python operations and expressions to JavaScript, and by monkey-patching that library by wrapping python variable references in val("...").

Use

In a YAML file, it's use looks something like this:

question: attribute test
fields:
  - Type goodbye: da_var
  - note: |
      See you later!
    live show if: da_var == "goodbye"

Technical Implementation

On the backend, when the parse.py module is loaded, it loads the metapensiero.pj.__main__.transform_string, overriding a few functions that convert the python AST to JavaScript's:

  • Attribute access (da_obj.attribute), subscripts (da_list[1] or da_dict["key"]), and simple variable names get wrapped in val("...") in JavaScript.
  • As seen in this js show if recipe, yesnomaybe return the string "None" for python's None, instead of JavaScript's null. We override to preserve this behavior. Someone could certainly write a python expression that uses None that shouldn't be the string "None", but it seems unlikely since you are restricted to variables on the page, where None is only used for those select cases.

The only substantial modification to existing code is that we can't transpile python to JS if that python still has Mako present, and we need to transpile the expressions before finding what variables are present in it. So I moved the search for variables later in the process. I think this adds a bit of runtime per screen as opposed to per interview load, but it's necessary, and in my testing didn't slow down things extensively.

On the frontend, it uses all of the same JavaScript as the js show if does, so no changes there.

Other considerations

The biggest consideration is the addition and monkey patching of the javascripthon or metapensiero.pj library as a dependency. From the TODO section of it's README, there aren't any major refactors or upcoming changes mentioned for the few places that we override, so IMO it's not too extensive of a change for our uses. It definitely a choice to be made though, so I'll leave it to you. I've added a demo here, and if this gets accepted, I'll make another PR documenting this further.

Footnotes

  1. Simple as compared to heavier ways to run python in the browser, such as brython or pyodide, which require a lot of extra javascript to be delivered to the user and make different assumptions about where the python variables referenced actually are.

Also:
* use `user_dict` when mako-izing show_if_js exprs
* correct typo of `yesnomaybe` type
* add example file in `docassemble_base` examples
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

1 participant