Skip to content

Support default variable value during lookup #4712

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

Open
oboehmer opened this issue Mar 31, 2023 · 3 comments
Open

Support default variable value during lookup #4712

oboehmer opened this issue Mar 31, 2023 · 3 comments

Comments

@oboehmer
Copy link
Contributor

oboehmer commented Mar 31, 2023

We're writing a few test cases which work on a large and nested dictionary which defines pretty much all variables in the test case. This yaml structure is also leveraged in a terraform provider which supports default values if the user does not specify a certain leaf in the data, as well as optional data which might not be filled in at all. This leads to some ugly code in Robot:

        FOR    ${intf}    IN    @{node.interfaces}
            ${sample_value}=    Evaluate   $intf.get('key', 1)

or

    IF    'key2' in $intf
        ${value}=   Set Variable   ${intf.key2}
    ELSE
        ${value}=   Set Variable   ${defaults.key2}
                ...

For things like this a Jinja2-like syntax like ${var | default} to look up the value from the var ${default} and maybe also ${var 'literal'} to retrieve it from a literal would come handy, using the alternative if ${var} is not defined.

I acknowledge the challenge to differentiate a default variable from a default literal (like None), but maybe we can come up with a solution..

@pekkaklarck
Copy link
Member

pekkaklarck commented Mar 31, 2023

With environment variables you can already do %{NAME=default} (#3382) and same syntax could we used also with normal variables. Basically ${var=default} would mean the value of ${var} if it exists and literal default otherwise. If you wanted the default value to be a variable, you needed to use ${var=${default}}. That's also how environment variables work.

There's a problem that we don't restrict variable names (perhaps we should) so it's possible that someone has used = in a variable name. We probably needed to implement this so that we first look is there a variable with the full name (e.g. var=default), and only look for possible = if there isn't.

We also needed to make sure there's no conflict with the extended variable syntax. For example, ${var==1} is valid nowadays and is resolved to True or False depending on is ${var} equal to 1 or not. In the future that could also be interpreted as being the value of ${var} or =1 if the variable doesn't exist. This ought to be a very rare conflict, but something we anyway need to take into account. Possibly we could require the default value separator = to immediately follow the variable name like ${var=default} and with extended variable syntax require there to be a space like ${var == 1}. This would require deprecating the ${var==1} usage but it shouldn't be too hard.

@pekkaklarck
Copy link
Member

pekkaklarck commented Mar 31, 2023

We also needed to decide do we allow the left side to be an extended variable usage like ${var.upper()=DEFAULT}. If we allow that, we then needed to decide should we use the default value only if there's no variable to begin with (e.g. ${var} wouldn't exist in the previous example), or should we use the default also if there's some error. For example, if ${var} in the previous example would be resolved to None, there would be an AttributeError and we could either report that or use the default value. In this case using the default could be fine, but we'd then also hide all syntax errors like ${var[0=default}.

A problem with allowing extended variable usage is that in that expression there can be equal signs as well and knowing what's the default value and what's part of the expression can be complicated. For example, something like ${var['='] if $var else '='=default}. A naïve approach would be splitting the variable part and default from the last =, but that would then prohibit using = in the default value itself.

Due to all this complexity, I believe the default value syntax should require the left side to be a variable directly. If you really wanted to, you could use nested variables like ${${var['='] if $var else '='}=default}. I also believe the default value syntax shouldn't be allowed with the inline Python evaluation syntax.

@manosnoam
Copy link

This feature can be quite useful for creating data in file templates.
For example, having a template that includes a test variable from a dictionary, using this format:
${dict[key]=defaultValue}

Currently it does not work and fails on:

Resolving variable '${dict[key]=defaultValue}' failed: SyntaxError: invalid syntax (, line 1)

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

3 participants